可以在 JSON 中使用注释吗?

json comments

我可以在 JSON 文件中使用注释吗?如果是这样,怎么做?

@StingyJack:解释可能不明显的事情,或者任何其他人可能对评论做的事情。我经常在数据文件中有评论。 XML、ini 文件和许多其他格式都包含注释条款。

如果您像我一样想知道 //comments 是否适用于 Sublime Text 配置文件的特定用例,答案是肯定的(从版本 2 开始)。 Sublime Text 至少不会抱怨它,而它会在控制台中抱怨 {"__comment": ...},因为它是一个意想不到的字段。

JSON5 支持注释:stackoverflow.com/a/7901053/108238

如果您想要带有注释的配置语言,请参阅 TOML

“我从 JSON 中删除了注释,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少注释会让一些人感到难过,但它不应该。” - Douglas Crockford(JSON 的作者),2012

M
Mateen Ulhaq

不。

JSON 是纯数据的。如果您包含评论,那么它也必须是数据。

您可以有一个名为 "_comment"(或其他名称)的指定数据元素,使用 JSON 数据的应用程序应忽略该数据元素。

您可能会更好地在生成/接收 JSON 的过程中添加注释,因为他们应该提前知道 JSON 数据是什么,或者至少知道它的结构。

但是,如果您决定:

{
   "_comment": "comment text goes here...",
   "glossary": {
      "title": "example glossary",
      "GlossDiv": {
         "title": "S",
         "GlossList": {
            "GlossEntry": {
               "ID": "SGML",
               "SortAs": "SGML",
               "GlossTerm": "Standard Generalized Markup Language",
               "Acronym": "SGML",
               "Abbrev": "ISO 8879:1986",
               "GlossDef": {
                  "para": "A meta-markup language, used to create markup languages such as DocBook.",
                  "GlossSeeAlso": ["GML", "XML"]
               },
               "GlossSee": "markup"
            }
         }
      }
   }
}

如果有一个名为 comment 的有效字段,则可能需要在实际评论上加上某种前缀:"__comment":"comment text goes here...",

顺便说一句,Java google-gson 的 json 库支持注释。

如果我想对 AccronymAbbrev 属性进行单独评论怎么办?我以前使用过这种模式,但因为它不允许我这样做而停止了。这是一个黑客。也许如果我用 __comment__ 代替属性名称。那是“__comment__Abbrev”,仍然是一个 hack,但会让我评论所有的 prpoerties

您也可以使用“//”:这看起来更原生,并且在同一个父级中仍然可以重复

当 JSON 用于人为设计的配置文件时,应该对它们进行注释以便人们更好地理解。注释,这样的文件不再是有效的 JSON,但是有解决方案。例如,Google 的 GYP 支持 # 样式的注释。 JSON.Minify 将帮助您从输入文件中丢弃 C/C++ 样式的注释。

C
Community

,JSON 中不允许使用 //…/*…*/ 形式的注释。这个答案基于:

https://www.json.org

RFC 4627:JavaScript 对象表示法 (JSON) 的 application/json 媒体类型

RFC 8259 JavaScript 对象表示法 (JSON) 数据交换格式(取代 RFC 4627、7158、7159)

如果您想用注释注释您的 JSON(从而使其无效 JSON),则在解析或传输之前将其缩小。 Crockford 本人在 2012 年在配置文件中承认了这一点。

@alkuzad:当涉及到形式语法时,必须有一些明确说明它们是允许的,而不是相反。例如,选择您的编程语言:仅仅因为某些期望(但缺少)的功能没有被明确禁止,并不意味着您的编译器会神奇地识别它。

是的。 JSON 格式在元素之间有很多死区,并且在这些区域中对空间不敏感,因此没有理由不能在其中添加单行或多行注释。许多解析器和压缩器也支持 JSON 注释,因此请确保您的解析器支持它们。 JSON 大量用于应用程序数据和配置设置,因此现在需要注释。 “官方规范”是一个好主意,但它还不够且过时,太糟糕了。如果您担心负载大小或性能,请缩小 JSON。

虽然你的答案是绝对正确的,但应该说这是BS。由于有如此多的最终用户遇到对 json 配置的需求,因此注释非常有用。仅仅因为一些锡箔帽决定 JSON 是并且必须始终是机器可读的,而忽略了人类需要阅读它的事实,恕我直言,这是对狭隘思想的讽刺。

@cmroanirgo:您显然不是第一个抱怨 JSON 限制的人......这就是为什么我们有静默允许注释的解析器以及 YAML 和 JSON5 等其他格式的原因。然而,这并没有改变 JSON 就是这样的事实。相反,我觉得有趣的是,人们开始使用 JSON 显然是不够的,因为存在问题。不要责怪 JSON 格式;责备自己坚持在不适合的地方使用它。

c
cmbuckley

如果您愿意,请包括评论;在解析或传输之前用压缩器将它们剥离。

我刚刚发布了 JSON.minify(),它从 JSON 块中去除注释和空格,使其成为可以解析的有效 JSON。因此,您可以像这样使用它:

JSON.parse(JSON.minify(my_str));

当我发布它时,我遭到了很多人的强烈反对,甚至不同意它的想法,所以我决定写一篇全面的博客文章来解释为什么comments make sense in JSON。它包括来自 JSON 的创建者的这条值得注意的评论:

假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有评论。然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。 - 道格拉斯·克罗克福德,2012

希望这对那些不同意 JSON.minify() 有用的人有所帮助。

JSON.minify() 唯一的问题是它真的很慢。所以我做了我自己的实现,做同样的事情: gist.github.com/1170297 。在一些大型测试文件上,您的实现需要 74 秒,而我的实现需要 0.06 秒。

如果您可以将建议的替代算法提交到 JSON.minify() 的 github 存储库,那就太好了,这样它就可以移植到所有受支持的语言:github.com/getify/json.minify

@MiniGod 我已经多次听到 Doug 对这个话题的想法。我很久以前在我的博文中提到过它们:blog.getify.com/json-comments

@MarnenLaibow-Koser 即使对于数据流(甚至数据包)的使用,注释仍然有效:包含诊断元数据(如创建时间或源)在 XML 中很常见,对于 JSON 数据也非常合理。反对评论的争论很肤浅,任何文本数据格式都应该允许评论,无论隐含的预期用途如何(没有规范建议 JSON 不能在其他地方使用,fwiw)

如果 JSON 要获得普遍接受(它基本上是这样),那么它应该具有普遍应用。示例:JSON 可以用作应用程序配置文件。此应用程序需要评论。

C
Community

设计上从 JSON 中删除了评论。

我从 JSON 中删除了注释,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少评论会让一些人感到难过,但不应该。假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有评论。然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。

来源:Public statement by Douglas Crockford on G+

我认为 JSON 应该比 XML 更易于阅读?注释是为了便于阅读。

无论如何,您可能会很顽皮并在 JSON 中添加解析指令: {"__directives":{"#n#":"DateTime.Now"}, "validdate":"#n#"}... 它看起来像 YAML那是前进的方向……

个人观点:不允许评论是蹩脚的。除了构建一个忽略注释的非标准 JSON 解析器来解码我的配置文件之外,我别无选择。

“我从 JSON 中删除了注释,因为我看到人们使用它们来保存解析指令”。按照这个逻辑,他也应该删除字符串类型。可怕的决定。

这就像要求所有的自行车都有辅助轮,因为有些人不会骑自行车。因为愚蠢的人滥用它而删除一个重要功能是糟糕的设计。数据格式应该优先考虑可用性而不是白痴。

l
laktak

JSON 不支持评论。它也从未打算用于需要注释的配置文件。

Hjson 是人类的配置文件格式。轻松的语法,更少的错误,更多的评论。

https://i.stack.imgur.com/u2E8q.gif

有关 JavaScript、Java、Python、PHP、Rust、Go、Ruby、C++ 和 C# 库的信息,请参阅 hjson.github.io

赞成。这显然是一个很好的变体,不开放的保守派人们只是喜欢讨厌。我希望你的实现能得到进一步的了解——甚至可能比原来的更受欢迎;)我希望有人也能用 Ruby 来实现它。 @adelphus 定义明确的语言是您自己的观点或意见。如果你是一个保守的“开发人员”,并不能证明你更好,你可能会更糟,把自己锁在有限的空间里。不要轻易将人们判断为糟糕的开发人员。

很抱歉,@konsolebox。或许您在阅读 ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf 后可能会重新考虑您的“定义明确的 JSON 是您的意见”的观点,这是一个真正的标准,开发人员实施他们自己的“特殊”版本会导致碎片化、混乱和大量时间浪费。看看 Web 开发人员在编写代码时留下的混乱,只是因为每个浏览器实现的标准版本略有不同。 JSON 语言可能并不完美,但碎片化更糟糕。是的,这只是一种观点,你可以自由反对。

我很佩服你的进取心,但你有点重新发明 YAML。如果您想要很多灵活性和人类可读性,请使用 YAML(实际上不要:stackoverflow.com/questions/450399/…)或坚持使用粗俗但明确的 JSON。

我发现最用户友好的配置格式仍然是 INI。它很简单,而且语法不是很重。这使得只是将脚趾浸入配置池中的用户不那么令人生畏。

每当您需要 json 作为配置时(需要注释的地方)- 将文件命名为“.js”而不是“.json”.. js 当然可以处理任何有效的 json 对象并且还可以处理注释.. 这就是它的原因“webpack.config.js”而不是“webpack.config.json”(在 webpack 中也有更多原因:P)

t
thanksd

免责声明:您的保修无效

正如已经指出的那样,这个黑客利用了规范的实现。并非所有 JSON 解析器都能理解这种 JSON。特别是流式解析器会窒息。

这是一个有趣的好奇心,但你真的不应该将它用于任何事情。以下是原答案。

我发现了一个小技巧,可以让您在 JSON 文件中放置注释,这不会影响解析,或以任何方式更改所表示的数据。

似乎在声明对象文字时,您可以使用相同的键指定两个值,并且最后一个优先。信不信由你,事实证明 JSON 解析器的工作方式相同。因此,我们可以使用它在源 JSON 中创建不会出现在已解析对象表示中的注释。

({a: 1, a: 2});
// => Object {a: 2}
Object.keys(JSON.parse('{"a": 1, "a": 2}')).length; 
// => 1

如果我们应用此技术,您的注释 JSON 文件可能如下所示:

{
  "api_host" : "The hostname of your API server. You may also specify the port.",
  "api_host" : "hodorhodor.com",

  "retry_interval" : "The interval in seconds between retrying failed API calls",
  "retry_interval" : 10,

  "auth_token" : "The authentication token. It is available in your developer dashboard under 'Settings'",
  "auth_token" : "5ad0eb93697215bc0d48a7b69aa6fb8b",

  "favorite_numbers": "An array containing my all-time favorite numbers",
  "favorite_numbers": [19, 13, 53]
}

上面的代码是 valid JSON。如果你解析它,你会得到一个像这样的对象:

{
    "api_host": "hodorhodor.com",
    "retry_interval": 10,
    "auth_token": "5ad0eb93697215bc0d48a7b69aa6fb8b",
    "favorite_numbers": [19,13,53]
}

这意味着没有评论的痕迹,也不会产生奇怪的副作用。

快乐黑客!

the specification:对象中的名称应该是唯一的。

不保证 JSON 中元素的顺序。这意味着“最后一个”项目可能会改变!

这显然违反了规范(见上面的评论),不要这样做。 ietf.org/rfc/rfc4627.txt?number=4627

否 - 如果解析器正在流式传输怎么办?如果解析器将其读入未定义键顺序的字典中怎么办?用火杀死它。

由于我们一直在 JSON 工作组的 IETF 研究 RFC 4627bis(加入我们并提供帮助!datatracker.ietf.org/wg/json),我们发现了实现者用于对象中重复名称的四种不同方法:使用第一种;使用最后一个;报告所有这些,让来电者选择一个;返回错误并停止解析。如果您的数据无法在所有这些方法中幸存下来,那么它在实践中将无法互操作。

h
habakuk

考虑使用 YAML。它几乎是 JSON 的超集(实际上所有有效的 JSON 都是有效的 YAML)并且它允许注释。

@NateS 很多人已经指出答案是否定的。我提出了一种更好的方法来实现 OP 的目标。这是一个答案。

@marnen-laibow-koser:是的,为 Java 和 Perl 使用可用的 YAML 库并期望每个生成的 YAML 被另一个无错误地使用肯定是无能的。 YAML 互操作是一个问题,但 JSON 互操作不是,这完全是由于我缺乏知识。

@marnen-laibow-koser,用更简单的规范完成同样事情的格式更好。具有完美实现的实用格式优于具有不完美实现的理想格式。并非所有错误库的责任都在实施者的肩上。 YAML 规范冗长、密集且迟钝。它的维基百科条目引用了两个模棱两可的例子;如果必须在人类和格式之间放置一个发射器以保护他们免受歧义,那么格式就失去了对人类友好的主张。 JSON 声明较少,并且大部分成功,而 YAML 声明较多且不足。

@marnen-laibow-koser,我已经驳斥了你对我自己无能的暗示,用细节支持我的主张,并稍微详细说明了我的偏好/偏见,这些偏好/偏见为我的 YAML 批评提供了依据。我自己的进一步评论可能收益递减。我对未来读者做出明智选择的能力充满信心。除了避开人身攻击之外,感谢您的演讲。如果您愿意,最后一句话是您的。

@toolbear 无意进行人身攻击。 “具有完美实现的实用格式优于具有不完美实现的理想格式”——我不确定我是否同意。如果格式是理想的(并且可实现的),那么人们总是可以做出很好的实现。如果格式不理想,那么即使是完美的实现也不会很好。 :) “YAML 规范长、密集、钝”——这实际上不是“钝”的意思,但 YAML 规范非常清楚。我没有看到维基百科中提到的任何歧义;如果我遗漏了什么,请引用文章的特定部分。

P
Peter Mortensen

你不能。至少这是我快速浏览 json.org 时的经验。

JSON 的语法在该页面上可视化。没有关于评论的任何注释。

t
t-b

注释不是官方标准,尽管一些解析器支持 C++ 样式的注释。我使用的是JsonCpp。在示例中有一个:

// Configuration options
{
    // Default encoding for text
    "encoding" : "UTF-8",

    // Plug-ins loaded at start-up
    "plug-ins" : [
        "python",
        "c++",
        "ruby"
        ],

    // Tab indent size
    "indent" : { "length" : 3, "use_space": true }
}

jsonlint 不验证这一点。所以注释是解析器特定的扩展而不是标准的。

另一个解析器是 JSON5

JSON TOML 的替代方案。

另一种选择是jsonc

最新版本的 nlohmann/json 提供了对忽略解析注释的可选支持。

Groovy 有一些 built-in classes for handling JSON。 JsonSlurper 可以处理评论。当然,官方规范中不允许注释,因此任何解析器中的这种行为都是非标准且不可移植的。

Newtonsoft Json.NET 也毫无问题地支持 C 风格的注释

恕我直言,这是该问题的最佳答案,因为它包含了许多确实支持的替代解析器的良好列表。不应鼓励使用重复或无关密钥的黑客行为,如果您想要/需要评论,您应该使用替代标准。

t
tagurit

以下是我在 Google Firebase documentation 中找到的允许您在 JSON 中添加评论的内容:

{
  "//": "Some browsers will use this to enable push notifications.",
  "//": "It is the same for all projects, this is not your project's sender ID",
  "gcm_sender_id": "1234567890"
}

仅供参考,Firebase 实时数据库不允许在键中使用“/”。所以这可能是您自己使用的一个很好的约定,但您不能在 Firebase 中这样做

此方法破坏了一些要求密钥必须唯一的库。我正在通过给评论编号来解决这个问题。

很好的评论,我在 SO 上发现了这个问题......这部分似乎没有被规范 stackoverflow.com/questions/21832701/…

我现在倾向于这样使用它: { "//foo": "foo comment", "foo": "foo value", "//bar": "bar comment", "bar": "bar value" }您可以将数组用于多个评论: { "//foo": [ "foo comment 1", "foo comment 2" ], "foo": ''foo value" }

P
Peter Mortensen

您应该改为写一个 JSON schema。 JSON 模式目前是一个提议的 Internet 草案规范。除了文档之外,该模式还可用于验证您的 JSON 数据。

例子:

{
    "description":"A person",
    "type":"object",
    "properties":
        {
            "name":
                {
                    "type":"string"
                },
            "age":
                {
                    "type":"integer",
                    "maximum":125
                }
        }
}

您可以使用描述架构属性来提供文档。

是的,json-schema google group 相当活跃,我建议使用 JSV 来实现 JSON Schema 验证器的良好 JavaScript 实现。

如果您使用 clojure(我相信您不使用),这里有一个功能合理的开源 JSON 模式解析器:github.com/bigmlcom/closchema

@Munhitsu Manatee.Json (.Net) 广泛支持 JSON 模式。

这并不适用于所有情况。我有一个手动配置的 JSON 以由具有自己架构的其他东西(包管理器)解析。我想要一个评论,例如 /* 最好使用 X 来代替另一个包管理器,但是那个管理器还没有提供 X。 */.

P
Peter Mortensen

如果您使用 Jackson 作为 JSON 解析器,那么您可以通过以下方式启用它以允许评论:

ObjectMapper mapper = new ObjectMapper().configure(Feature.ALLOW_COMMENTS, true);

然后你可以有这样的评论:

{
  key: "value" // Comment
}

您还可以通过设置以 # 开头的评论:

mapper.configure(Feature.ALLOW_YAML_COMMENTS, true);

但总的来说(如前所述)规范不允许评论。

这是可逆的吗?如果您加载文件并将其写回怎么办?

K
Karina Kozarova

不。 JSON 曾经支持评论,但它们被滥用并从标准中删除。

来自 JSON 的创建者:

我从 JSON 中删除了注释,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少评论会让一些人感到难过,但不应该。 - 道格拉斯·克罗克福德,2012

官方 JSON 站点位于 JSON.org。 JSON 被 ECMA International 定义为 standard。总是有一个请求过程来修改标准。出于多种原因,不太可能将注释添加到 JSON 标准中。

JSON 在设计上是一种易于逆向工程(人工解析)的 XML 替代方案。它甚至被简化到不需要注释的地步。它甚至不是一种标记语言。目标是稳定性和互操作性。

任何理解面向对象的“具有”关系的人都可以理解任何 JSON 结构——这就是重点。它只是一个带有节点标签(键/值对)的有向无环图(DAG),是一种近乎通用的数据结构。

唯一需要的注释可能是“//这些是 DAG 标记”。键名可以根据需要提供信息,允许任意语义。

任何平台都可以只用几行代码解析 JSON。 XML 需要复杂的 OO 库,这些库在许多平台上不可行。

注释只会降低 JSON 的互操作性。除非您真正需要的是标记语言 (XML),否则根本没有其他要添加的内容,并且不关心您的持久数据是否易于解析。

但是正如 JSON 的创建者也观察到的那样,JS 管道一直支持评论:

继续并插入您喜欢的所有评论。然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。 - 道格拉斯·克罗克福德,2012

C
Community

如果您使用带有 ASP.NET 的 Newtonsoft.Json 库来读取/反序列化,您可以在 JSON 内容中使用注释:

//"name": "string" //"id": int

或者

/* 这是一个注释示例 */

PS:单行注释仅支持 6+ 版本的 Newtonsoft Json。

对无法开箱即用的人的附加说明:我在我制作的 ASP.NET Web 应用程序中使用 JSON 格式进行基本设置。我阅读了该文件,使用 Newtonsoft 库将其转换为设置对象,并在必要时使用它。

我更喜欢在 JSON 文件本身中写关于每个单独设置的注释,而且我真的不关心 JSON 格式的完整性,只要我使用的库可以接受它。

我认为这是一种比创建单独的“settings.README”文件并解释其中的设置更容易使用/理解的方式。

如果您对这种用法有疑问;对不起,精灵不在灯里了。人们会发现 JSON 格式的其他用途,对此您无能为力。

很难理解为什么有人会在陈述事实时遇到问题。

我会假设有人例外,因为上面不再是 JSON,或者是无效的 JSON。也许添加一个简短的免责声明会安抚。

我完全同意你的看法,但到目前为止,有 883 人赞成不回答只是说明显而易见的问题。意识形态纯度高于有用的信息,对你来说就是这样。

关键是带有注释的文件不是 JSON,许多 JSON 库都无法解析。随意在自己的程序中做任何你想做的事情,但带有注释的文件不是 JSON。如果您声称它是,那么人们将尝试用他们选择的语言/库来解析它,它会失败。这就像问是否可以在 XML 中使用方括号代替尖括号。你可以做任何你想做的事,但它不再是 XML。

如果解析器实现发生变化,可能会出现问题。

R
Randika Vishman

如果您的文本文件(一个 JSON 字符串)将被某个程序读取,那么在使用它之前去掉 C 或 C++ 样式的注释会有多困难?

答:应该是单排。如果你这样做,那么 JSON 文件可以用作配置文件。

可能是迄今为止最好的建议,尽管将文件保留为交换格式仍然是一个问题,因为它们需要在使用前进行预处理。

我同意并用 Java 编写了一个 JSON 解析器,可以在 www.SoftwareMonkey.org 上找到,它就是这样做的。

尽管我认为,扩展 JSON 并不是一个好主意(不称其为不同的交换格式):确保忽略字符串中的“注释”。 { "foo": "/* 这不是评论。*/" }

“...将是一个单行” 嗯,不,实际上,JSON 不是正则表达式可以简单地找到匹配的 /* 对的正则语法。您必须解析文件以查找 /* 是否出现在字符串中(并忽略它),或者是否已转义(并忽略它)等。此外,您的答案也无济于事,因为您只是推测(错误地)而不是提供任何解决方案。

@kyle-simpson 说了什么。此外,他过于谦虚,无法将读者引向他自己关于使用 JSON.minify 作为临时正则表达式的替代方案的答案。做那个,不是这个。

t
tagurit

JSON 本身不支持评论,但是您可以制作自己的解码器或至少预处理器来去除评论,这非常好(只要您忽略评论并且不使用它们来指导您的应用程序应该如何处理 JSON 数据)。

JSON 没有评论。 JSON 编码器不得输出评论。 JSON 解码器可以接受和忽略评论。

永远不应该使用评论来传递任何有意义的东西。这就是 JSON 的用途。

参见:Douglas Crockford, author of JSON spec

Crockford 后来继续写道:“假设您使用 JSON 来保存您想要注释的配置文件。继续插入您喜欢的所有注释。然后通过 JSMin 将其传递给您的 JSON 解析器。”有关更多信息,请参阅@kyle-simpson 关于 JSON.minify 的回答。

P
Peter Mortensen

JSON 背后的想法是在应用程序之间提供简单的数据交换。这些通常是基于网络的,语言是 JavaScript。

它实际上不允许这样的注释,但是,将注释作为数据中的名称/值对之一传递肯定会起作用,尽管该数据显然需要被解析代码忽略或专门处理。

综上所述,JSON 文件不应该包含传统意义上的注释。它应该只是数据。

查看 JSON website 了解更多详情。

JSON格式确实没有注释。我个人认为这是一个重大错误——将注释作为元数据(而不是数据)的能力对于 xml 非常有用。 JSON 规范的早期草案版本确实包含注释,但由于某种原因它们被删除了。 :-/

@StaxMan 它们被删除正是因为人们开始将它们用作元数据。 Crockford 说它破坏了格式设计的兼容性,我同意:如果您想要元数据,为什么不将其作为实际数据包含在内?用这种方式解析更容易。

元数据属于元数据结构(例如 HTML 标签),而不是评论。滥用元数据评论只是在不存在真正元数据结构的情况下使用的一种黑客行为。

P
Peter Mortensen

我只是在配置文件中遇到这个。我不想使用 XML(冗长、图形化、丑陋、难以阅读)或“ini”格式(没有层次结构、没有真正的标准等)或 Java“Properties”格式(如 .ini)。

JSON 可以做他们能做的所有事情,但它不那么冗长,而且更易于阅读——而且解析器在许多语言中都很容易且无处不在。它只是一棵数据树。但是带外注释通常是记录“默认”配置等的必要条件。配置永远不会是“完整文档”,而是在需要时可供人类阅读的已保存数据树。

我想可以将 "#": "comment" 用于“有效”JSON。

对于配置文件,我建议使用 YAML,而不是 JSON。它(几乎)是 JSON 的一个更强大的超集,但也支持更易读的结构,包括注释。

@Hamidam 十多种语言支持 yaml:yaml.org - 但您可以问有多少支持内置,而不需要第三方库依赖项。看起来像 Ruby 1.9.2 一样。有人知道其他人吗?哪些语言默认支持 json?

YAML 互操作是一个谎言: stackoverflow.com/questions/450399/… 。如果您的直觉是将 JSON 用于配置文件,请遵循它。

C
Community

这取决于您的 JSON 库。 Json.NET 支持 JavaScript 样式的注释,/* commment */

请参阅another Stack Overflow question

我相信这就是为什么我在这个 ASP.NET vNext 预览页面(在 package.json 下)的屏幕截图中看到评论的原因:blogs.msdn.com/b/webdev/archive/2014/06/03/… 虽然我还没有在规范中找到任何内容。

t
tagurit

JSON 对于配置文件和其他本地使用很有意义,因为它无处不在,而且比 XML 简单得多。

如果人们在交流数据(无论是否有效)时有充分的理由反对在 JSON 中添加评论,那么 JSON 可能会被分成两部分:

JSON-COM:在线上的 JSON,或在传输 JSON 数据时应用的规则。

JSON-DOC:JSON 文档,或文件中或本地的 JSON。定义有效 JSON 文档的规则。

JSON-DOC 将允许注释,并且可能存在其他细微差异,例如处理空格。解析器可以轻松地从一种规范转换为另一种规范。

关于 Douglas Crockford 在此问题上提出的remark(@Artur Czajka 引用)

假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有评论。然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。

我们正在谈论一个通用的配置文件问题(跨语言/平台),而他正在用一个 JS 特定的实用程序来回答!

当然,特定于 JSON 的缩小可以用任何语言实现,但是将其标准化,以便它在所有语言和平台的解析器中无处不在,这样人们就不会因为缺少该功能而浪费时间,因为他们有很好的用例,在在线论坛,并让人们告诉他们这是一个坏主意,或者建议很容易实现从文本文件中删除评论。

另一个问题是互操作性。假设您有一个库或 API 或任何类型的子系统,其中有一些与之关联的配置或数据文件。并且这个子系统可以从不同的语言中访问。然后你会告诉人们:顺便说一下,在将 JSON 文件传递给解析器之前不要忘记从 JSON 文件中删除注释!

无需对 JSON 进行分段。带注释的 JSON 不再是 JSON。但是用注释来注释你的 JSON 是完全可以接受的,只要你确保在解析或传输它之前去掉它们。这样做绝不应该是接收者的责任。

A
Audrius Meškauskas

,新标准,JSON5 允许 C++ 样式注释,其中有许多 other extensions

// A single line comment.

/* A multi-
   line comment. */

JSON5 数据交换格式 (JSON5) 是 JSON 的超集,旨在减轻 JSON 的一些限制。它完全向后兼容,使用它可能比编写自定义非标准解析器、为现有解析器打开非标准功能或使用各种技巧(如字符串字段进行注释)更好。或者,如果使用的解析器支持,只需同意我们使用 JSON 5 子集,即 JSON 和 C++ 样式注释。它比我们以我们认为合适的方式调整 JSON 标准要好得多。

已经有 npm packagePython packageJava packageC library 可用。它向后兼容。我认为没有理由坚持“官方”JSON 限制。

我认为从 JSON 中删除注释的原因与在 Java 中删除运算符重载的原因相同:可能会以错误的方式使用,但忽略了一些明显合法的用例。对于运算符重载,它是矩阵代数和复数。对于 JSON 注释,它是可以由人类编写、编辑或读取的配置文件和其他文档,而不仅仅是解析器。

JSON5 是“非常”的标准吗?还是还在被收养?我的意思是……我可以期望 2021 年的任何框架都能理解 Json5 吗?或者很可能不是?

如果您创建自己的标准,那么您是世界上唯一使用它的人。像 JSON5 这样的东西可能更好。

不是要创建我的标准……只是想知道是时候考虑 JSON5 还是更好地坚持“旧 JSON”,然后再等几个月再花时间进行探索。

JSON5 不是“新标准”——它是由不同的人开发的独立标准。

P
Peter Mortensen

如果您使用 JSON5,则可以包含评论。

JSON5 是对 JSON 的提议扩展,旨在使人类更容易手动编写和维护。它通过直接从 ECMAScript 5 添加一些最小的语法特性来做到这一点。

你能添加一个例子吗?那么你实际上可能需要那些额外的字符。

SO指南要求提供实际答案。不需要仅链接的答案。您可以查看指南stackoverflow.com/help/how-to-answer

SO 由其用户主持。这意味着如果我有答案,我可以提供答案,如果它不遵循指导方针,我可以评论你的答案。这就是 SO 如何成为一个很好的资源。

P
Peter Mortensen

Dojo Toolkit JavaScript 工具包(至少从 1.4 版开始)允许您在 JSON 中包含注释。评论可以是 /* */ 格式。 Dojo Toolkit 通过 dojo.xhrGet() 调用使用 JSON。

其他 JavaScript 工具包也可以类似地工作。

在选择最终选项之前尝试替代数据结构(甚至数据列表)时,这会很有帮助。

不,不是这个。 JSON 没有评论。如果您选择使用注释来注释您的 JSON,请在解析或传输之前将其缩小。这不应该是接收者的责任。

我没有说 JSON 有评论。我也不是暗示将它们包含在您的 JSON 中是合适的,尤其是在生产系统中。我说过 Dojo 工具包允许您添加它们,这是(或至少是)事实上是正确的。在您的测试阶段,有非常有用的用例可供您这样做。

提供评论是不好的巫术,因此 JSON 无效,dojo.xhrGet() 通过接受隐含鼓励。

我仍然投票支持升级 JSON 规范以允许评论。我完全赞成在传输 JSON 之前缩小和剥离评论,但没有任何能力以任何标准方式评论你的 JSON,而不必在解析它之前通过单独的实用程序传递它,这似乎很愚蠢。我还让您无法在 JSON 配置文件上使用 JSON 编辑器,因为您的文件不是有效的 JSON。

P
Peter Mortensen

JSON 不是框架协议。它是一种无语言格式。所以评论的格式没有为 JSON 定义。

正如许多人所建议的那样,有一些技巧,例如,您可以使用重复键或特定键 _comment。由你决定。

P
Peter Mortensen

免责声明:这很愚蠢

实际上有一种方法可以添加注释并保持在规范范围内(不需要额外的解析器)。但是,如果没有任何类型的解析,它不会产生人类可读的评论。

您可能会滥用以下内容:

在任何标记之前或之后都允许使用无关紧要的空格。空格是以下一个或多个代码点的任意序列:字符制表符 (U+0009)、换行符 (U+000A)、回车符 (U+000D) 和空格 (U+0020)。

您可以以一种骇人听闻的方式滥用它来添加评论。例如:使用选项卡开始和结束您的评论。在 base3 中编码注释并使用其他空白字符来表示它们。例如。

010212 010202 011000 011000 011010 001012 010122 010121 011021 010202 001012 011022 010212 011020 010202 010202

(ASCII 中的 hello base three)但不是 0 使用空格,1 使用换行,2 使用回车。

这只会给你留下很多不可读的空白(除非你制作一个 IDE 插件来动态编码/解码它)。

出于明显的原因,我什至从未尝试过,你也不应该这样做。

这很有趣。

t
tagurit

可以JSONP 中添加评论,但不能使用纯 JSON。我刚刚花了一个小时试图让我的程序与 this example from Highcharts 一起工作。

如果你点击链接,你会看到

?(/* AAPL historical OHLC data from the Google Finance API */
[
/* May 2006 */
[1147651200000,67.79],
[1147737600000,64.98],
...
[1368057600000,456.77],
[1368144000000,452.97]
]);

因为我的本地文件夹中有一个类似的文件,所以 Same-origin policy 没有问题,所以我决定使用纯 JSON……当然,$.getJSON 因为评论而默默地失败了。

最后,我只是向上面的地址发送了一个手动 HTTP 请求,并意识到内容类型是 text/javascript,因为 JSONP 返回纯 JavaScript。在这种情况下,评论是允许的。但是我的应用程序返回了内容类型 application/json,所以我不得不删除评论。

t
tagurit

这是一个“你能不能”的问题。这是一个“是”的答案。

不,您不应该使用重复的对象成员将侧通道数据填充到 JSON 编码中。 (请参阅“对象中的名称应该是唯一的”in the RFC)。

是的,你可以insert comments around the JSON,你可以解析出来。

但是,如果您想要一种将任意侧通道数据插入和提取到有效 JSON 的方法,这里有一个答案。我们利用 JSON 编码中数据的非唯一表示。这在 RFC 的第二部分中是允许的*“在六个结构字符中的任何一个之前或之后允许空白”。

RFC 仅声明“在六个结构字符之前或之后允许使用空格”,没有明确提及字符串、数字、“false”、“true”和“null”。在所有实现中都会忽略此省略。

首先,通过缩小 JSON 来规范化它:

$jsonMin = json_encode(json_decode($json));

然后将您的评论编码为二进制:

$hex = unpack('H*', $comment);
$commentBinary = base_convert($hex[1], 16, 2);

然后 steg 你的二进制文件:

$steg = str_replace('0', ' ', $commentBinary);
$steg = str_replace('1', "\t", $steg);

这是您的输出:

$jsonWithComment = $steg . $jsonMin;

RFC 仅声明“在六个结构字符之前或之后允许使用空格”,没有明确提及字符串、数字、“false”、“true”、“null”。在所有实现中都会忽略此省略。

为了获得更大的评论密度,您不能将您的评论编码为三进制并使用空格、制表符和换行符来进行处理吗?

应该不是必须的。请参阅明确包含的 RFC 2119:必须:该词或术语“REQUIRED”或“SHALL”表示定义是规范的绝对要求。 ...应该:这个词,或形容词“推荐”,意味着在特定情况下可能存在忽略特定项目的正当理由,但在选择不同的课程之前,必须理解并仔细权衡全部含义。

很好的参考。反对使用重复键的更好理由是标准的引用“当对象中的名称不唯一时,接收此类对象的软件的行为是不可预测的。”。现在我也明白了为什么标准不是“必须是唯一的”,这使得验证器更简单,它只需要跟踪 [ 和 {,它不需要知道已经使用了哪些键。

t
tagurit

JSON 本身不允许评论。推理是完全愚蠢的,因为您可以使用 JSON 本身来创建注释,这完全消除了推理,并且完全没有充分理由加载解析器数据空间以获得完全相同的结果和潜在问题,例如它们是:JSON带有评论的文件。

如果您尝试在其中添加注释(例如使用 // 或 /* */ 或 #),则某些解析器将失败,因为这严格不符合 JSON 规范。所以你永远不应该那样做。

例如,在这里,我的 image manipulation system 保存了图像符号和一些与它们相关的基本格式化(评论)信息(在底部):

{
    "Notations": [
        {
            "anchorX": 333,
            "anchorY": 265,
            "areaMode": "Ellipse",
            "extentX": 356,
            "extentY": 294,
            "opacity": 0.5,
            "text": "Elliptical area on top",
            "textX": 333,
            "textY": 265,
            "title": "Notation 1"
        },
        {
            "anchorX": 87,
            "anchorY": 385,
            "areaMode": "Rectangle",
            "extentX": 109,
            "extentY": 412,
            "opacity": 0.5,
            "text": "Rect area\non bottom",
            "textX": 98,
            "textY": 385,
            "title": "Notation 2"
        },
        {
            "anchorX": 69,
            "anchorY": 104,
            "areaMode": "Polygon",
            "extentX": 102,
            "extentY": 136,
            "opacity": 0.5,
            "pointList": [
                {
                    "i": 0,
                    "x": 83,
                    "y": 104
                },
                {
                    "i": 1,
                    "x": 69,
                    "y": 136
                },
                {
                    "i": 2,
                    "x": 102,
                    "y": 132
                },
                {
                    "i": 3,
                    "x": 83,
                    "y": 104
                }
            ],
            "text": "Simple polygon",
            "textX": 85,
            "textY": 104,
            "title": "Notation 3"
        }
    ],
    "imageXW": 512,
    "imageYW": 512,
    "imageName": "lena_std.ato",
    "tinyDocs": {
        "c01": "JSON image notation data:",
        "c02": "-------------------------",
        "c03": "",
        "c04": "This data contains image notations and related area",
        "c05": "selection information that provides a means for an",
        "c06": "image gallery to display notations with elliptical,",
        "c07": "rectangular, polygonal or freehand area indications",
        "c08": "over an image displayed to a gallery visitor.",
        "c09": "",
        "c10": "X and Y positions are all in image space. The image",
        "c11": "resolution is given as imageXW and imageYW, which",
        "c12": "you use to scale the notation areas to their proper",
        "c13": "locations and sizes for your display of the image,",
        "c14": "regardless of scale.",
        "c15": "",
        "c16": "For Ellipses, anchor is the  center of the ellipse,",
        "c17": "and the extents are the X and Y radii respectively.",
        "c18": "",
        "c19": "For Rectangles, the anchor is the top left and the",
        "c20": "extents are the bottom right.",
        "c21": "",
        "c22": "For Freehand and Polygon area modes, the pointList",
        "c23": "contains a series of numbered XY points. If the area",
        "c24": "is closed, the last point will be the same as the",
        "c25": "first, so all you have to be concerned with is drawing",
        "c26": "lines between the points in the list. Anchor and extent",
        "c27": "are set to the top left and bottom right of the indicated",
        "c28": "region, and can be used as a simplistic rectangular",
        "c29": "detect for the mouse hover position over these types",
        "c30": "of areas.",
        "c31": "",
        "c32": "The textx and texty positions provide basic positioning",
        "c33": "information to help you locate the text information",
        "c34": "in a reasonable location associated with the area",
        "c35": "indication.",
        "c36": "",
        "c37": "Opacity is a value between 0 and 1, where .5 represents",
        "c38": "a 50% opaque backdrop and 1.0 represents a fully opaque",
        "c39": "backdrop. Recommendation is that regions be drawn",
        "c40": "only if the user hovers the pointer over the image,",
        "c41": "and that the text associated with the regions be drawn",
        "c42": "only if the user hovers the pointer over the indicated",
        "c43": "region."
    }
}

“推理”链接已损坏。有没有机会找到它的当前链接?

唐,不幸的是,谷歌已经杀死了包含该帖子的社交媒体系统;我不知道原始海报从那里去哪里,如果在任何地方。不过,我将删除上述信息中的链接,以消除歧义。谢谢。

推理并不愚蠢,您只是证明了这一点。将注释实现为标签可以保留互操作性。这正是 Crockford 想要将评论解析为标签的原因。现在一切都只是一个标签并以相同的方式解析。

如果规范声明“以 # 开头的行是注释”,那么这将是完全可互操作的。就目前而言,注释都加载了解析器空间,因为它们是有效的解析项,而不是被理解为注释,并且它们对于存在的每个 .json 文件都可能不同。然而,如果(例如)规范说“以 # 开头的行是注释”,那么解析器可以跳过这些行而不进行解析(更快)并且不加载解析器空间(更好的内存利用率。)缺乏没有任何好处.json 中的评论,只有缺点。

W
WilliamK

就我而言,我需要在 JSON 输出之前使用注释进行调试。所以我把调试信息放在HTTP头中,避免破坏客户端:

header("My-Json-Comment: Yes, I know it's a workaround ;-) ");

https://i.stack.imgur.com/yMh3J.png

J
Joy

我们将 strip-json-comments 用于我们的项目。它支持类似的东西:

/*
 * Description 
*/
{
    // rainbows
    "unicorn": /* ❤ */ "cake"
}

只需 npm install --save strip-json-comments 即可安装和使用它,例如:

var strip_json_comments = require('strip-json-comments')
var json = '{/*rainbows*/"unicorn":"cake"}';
JSON.parse(strip_json_comments(json));
//=> {unicorn: 'cake'}

请注意,当 json 包含这些专有注释时,它不再是有效的 JSON。

strip-json-comments 在哪个上下文中运行?节点.js?

@PeterMortensen 我尝试了 node.js。您可以尝试是否适用于客户端js。