JSON的替代方案(用于指定配置)有哪些?

15
我喜欢使用json作为我编写的软件的配置文件格式。我喜欢它轻量级、简单易用且广泛支持。然而,我发现在json中有些我真正需要的功能是缺失的。
Json没有多行字符串或here documents(http://en.wikipedia.org/wiki/Here_document),当你想要使你的json文件更具可读性和可编辑性时,这通常会很尴尬。你可以使用字符串数组,但那只是一个笨拙的解决方法。
Json不允许注释。
如果你看一下Unix配置文件的格式,你会发现很多人都设计了自己的笨拙格式来处理一些本应该使用某种通用工具完成的事情。例如,以下是Apache配置文件中的一些代码:
RewriteEngine on
RewriteBase /temp
RewriteCond %{HTTP_ACCEPT} application/xhtml\+xml
RewriteCond %{HTTP_ACCEPT} !application/xhtml\+xml\s*;\s*q=0
RewriteCond %{REQUEST_URI} \.html
RewriteCond %{THE_REQUEST} HTTP/1\.1
RewriteRule t\.html t.xhtml [T=application/xhtml+xml]

基本上,这里正在发生的是他们发明了一种极其痛苦的方式来编写布尔函数f(w,x,y,z)= w&!x&y&z。你想要逻辑“或”吗?他们也有一些单独的(丑陋的)机制。

这似乎指向一种数据描述语言,它简单而图灵不完备,但仍比json更具表现力,灵活和方便。有人知道这样的语言吗?

对我来说,XML太复杂了,lisp表达式具有错误的特性(图灵完备性),缺少正确的特性(文档,表达性语法)。

【编辑】标题有误。我实际上对json的下一次迭代不感兴趣。我对JavaScript子集的语言不感兴趣。我对替代数据描述语言感兴趣。


3
YAML是一种人类可读性强的数据序列化格式,常用于配置文件和网络传输。它的语法简洁易懂,使用空格进行结构表示,不需要繁琐的标点符号。YAML可以支持各种编程语言,并且有着广泛的应用领域,如开发框架、云平台等。 - BalusC
@BalusC:有趣的建议 :-) 但是 YAML 似乎没有提供任何漂亮的方法来执行布尔函数/Apache 示例,或者类似风格的应用程序。 - user1142217
9个回答

5
EDN格式是一种基于Clojure字面量的选项之一。它几乎是JSON的超集,除了在映射中没有特殊符号分隔键和值(如JSON中的:);相反,所有元素都由空格和/或逗号分隔,并且映射编码为具有偶数个元素的列表,括在{..}中。
EDN允许使用注释(使用;到换行符或使用#_到下一个元素的结尾),但不能使用此文档。使用tag符号可以将EDN扩展到新类型:
#myapp/Person {:first "Fred" :last "Mertz"}
myapp/Person标签的参数(即{:first "Fred" :last "Mertz"})必须是一个有效的EDN表达式,这使得它不支持here-doc语法。

它有两个内置标签:#inst用于时间戳和#uuid。它还支持命名空间符号(即标识符)和关键字(即映射键常量)类型;它区分列表(..)和向量[..]。任何类型的元素都可以用作映射中的键。

在您上述问题的情况下,可以发明一个#apache/rule-or标签,它接受一系列元素,其语义由您决定!


4

请查看http://github.com/igagis/puu/

它比JSON还要简单。

它有C++样式的注释。

可以格式化多行字符串,并使用转义换行符\ n和制表符\ t字符,如果需要“真正”的换行或标签。

这是示例片段:

"String object"
AnotherStringObject
"String with children"{
    "child 1"
    Child2
    "child three"{
        SubChild1
        "Subchild two"

        Property1 {Value1}
        "Property two" {"Value 2"}
        //comment

        /* multi-line
           comment */

        "multi-line
         string"

        "Escape sequences \" \n \r \t \\"
    }

R"qwerty(
This is a
raw string, "Hello world!"
int main(argc, argv){
    int a = 10;
    printf("Hello %d", a);
}
)qwerty"
}

这就是一见钟情。它甚至拥有原始字符串字面量的强大功能。 - Abdurrahim
很高兴你喜欢它。不幸的是,原始字符串支持只在 C++ 库中实现了。C# 和 Java 库目前缺乏原始字符串支持。 - igagis
看来是时候协同开发操作系统了,尤其是需要改进 C# 库,感觉像是由一位 C++ 开发人员编写的 :) - Abdurrahim

3
考虑使用TOML。 TOML是一种针对配置设计的语言。它看起来非常友好且功能强大。易于阅读并支持广泛的数据类型和结构。有许多语言的解析器: C C# C++ Common Lisp Crystal Dart Erlang Fortran Go Janet Java JavaScript Julia Kotlin Lua Nim OCaml Perl Perl6/Raku Python Rust Swift V

ToML被用于gradle的依赖版本定义中 https://docs.gradle.org/current/userguide/platforms.html#sub:conventional-dependencies-toml - Anarchofascist

2

自从2018年3月以来,您可以使用JSON5,它似乎已经添加了您(和许多其他人)从JSON中缺失的所有内容。

简短示例(JSON5)

{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}

JSON5数据交换格式(JSON5)是JSON的超集,旨在通过扩展其语法以包括ECMAScript 5.1中的一些产生物来缓解JSON的某些限制。
功能摘要: 以下 ECMAScript 5.1 的特性,在 JSON 中不支援,已被擴充至 JSON5。
对象: - 对象键名可以是一个 ECMAScript 5.1 标识符名称。 - 对象可以有单个尾随逗号。
数组: - 数组可以有单个尾随逗号。
字符串: - 字符串可以使用单引号。 - 字符串可以通过转义换行符跨越多行。 - 字符串可以包含字符转义符。
数字: - 数字可以是十六进制。 - 数字可以有前导或尾随小数点。 - 数字可以是 IEEE 754 正无穷、负无穷和 NaN。 - 数字可以以显式加号开头。
注释: - 允许单行和多行注释。
空格: - 允许使用其他空格字符。

GitHub: https://github.com/json5/json5

GitHub: https://github.com/json5/json5


公平地说,JSON5 中的注释支持是部分的,因为在将配置保存回 JSON 后,JSON5 不会保留注释(即您只能在只读配置文件中使用 JSON5 中的注释,因为 JSON5.stringify() 返回没有注释的 json)。 - tav
@tav 绝对正确,因为评论只是针对开发人员的。一旦解析内容,评论就已经被遗失了。因此这并不是“stringify”的错。这是预期发生的事情。另一个例子:编译后的Java类不包含评论。反编译一个你就找不到它们。 - DJDaveMark
缺乏JSON5中的本地正则表达式支持真的让我感到沮丧。 - Marshal
@Marshal 这是关于为什么本地正则表达式支持未能进入 JSON5 v1.0 的讨论的链接:(https://github.com/json5/json5/issues/91#issuecomment-197048166)。我倾向于同意这个决定。对我来说,将正则表达式作为字符串并没有太大影响。 - DJDaveMark
@DJDaveMark 感谢提供链接。实验性功能是否仍未包含在当前的JSON5版本中?如果是,那么目前建议的正则表达式字符串化方式是使用replacer函数吗?谢谢。 - Marshal

1

JSON 中的 'J' 是 "Javascript"。如果一个特定的所需语法结构不在 Javascript 中,则它也不会在 JSON 中出现。

Heredocs 超出了 JSON 的范围。这是一个用于简化多行字符串定义的语言语法结构,但 JSON 是一种传输符号。它与构造无关。但是,它确实具有多行字符串,只需允许字符串中的 \n 换行字符即可。在 JSON 中没有任何东西说你不能在一个字符串中有一个换行符。只要包含的引号字符是正确的,它就是完全有效的。例如:

{"x":"y\nz"}

是100%合法有效的JSON,并且是一个多行字符串,而

{"x":"y
z"} 

这不会被解析,也将失败。


1
如果在JavaScript中没有特定所需的语法结构,则它不会出现在JSON中。这很可爱,但是JSON实际上不是JavaScript的子集,并支持JavaScript不支持的内容。 - remmy

1

总有一种我喜欢称之为“真正的JSON”。JSON代表JavaScript对象表示法,而JavaScript确实有注释和类似于heredocs的东西。

对于heredoc,您可以使用JavaScript的E4X内联XML:

{
    longString: <>
                Hello, world!
                This is a long string made possible with the magic of E4X.
                Implementing a parser isn't so difficult.
                </>.toString() // And a comment
    /* And another
       comment */
}

你可以使用Firefox的JavaScript引擎(FF是目前唯一支持E4X的浏览器),或者你可以实现自己的解析器,这并不是很困难。

这里也有E4X快速入门指南。


有趣的想法,尽管它不符合图灵不完备性的标准。 - user1142217
有什么方法可以压缩空格以节省网络带宽?谢谢。 - Aizzat Suhardi
1
@AizzatSuhardi:使用实际的JSON。 - Ry-
@minitech♦:你的意思是 {"actualJson":"嗨!\n我是真正的JSON"} 吗? - Aizzat Suhardi

0
JSON的一个重要属性(也许是最重要的)是你可以轻松地在字符串表示和对象形式之间“翻转”,用于表示对象形式的对象相对简单,只是数组和映射。这就是JSON在网络环境中如此有用的原因。
你想要的函数会与JSON的这种双重性质发生冲突。

0

对于配置,您可以使用可嵌入的脚本语言,例如lua或python,事实上,这对于配置来说并不是一件罕见的事情。这使您可以使用多行字符串或文档以及注释。它还使得像您描述的布尔函数之类的东西更容易。然而,脚本语言当然是图灵完备的。


0

还有ELDF

虽然它不支持注释,但可以通过空键来模拟:

config_var1 = value1
=some comment
config_var2 = value2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接