可以在 JSON 中使用注释吗?
Posted
技术标签:
【中文标题】可以在 JSON 中使用注释吗?【英文标题】:Can comments be used in JSON? 【发布时间】:2010-09-19 16:12:51 【问题描述】:我可以在 JSON 文件中使用 cmets 吗?如果有,怎么做?
【问题讨论】:
@StingyJack:解释可能不明显的事情,或者任何其他人可能对 cmets 做的事情。我经常在数据文件中有 cmets。 XML、ini 文件和许多其他格式包括对 cmets 的规定。 如果你和我一样想知道//comments
是否适合 Sublime Text 配置文件的特定用例,答案是肯定的(从版本 2 开始)。 Sublime Text 至少不会抱怨它,而它会在控制台中抱怨"__comment": ...
,因为它是一个意想不到的字段。
JSON5 支持 cmets:***.com/a/7901053/108238
JSON 的主要目标之一是消除 XML 等格式的样板。这都是关于数据和最小标记的。这是一种自以为是的格式,明确阻止您使用 cmets。 json-schema 将在某种程度上帮助人们理解数据,类似于 XML 模式,但工具支持需要改进。 JSON 已经渗透到其他领域,而不是现在通过 Internet 传输,我同意它与 cmets 一起使用会很方便。
"我从 JSON 中删除了 cmets,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少 cmets 会让一些人感到难过,但它不应该吨。” - Douglas Crockford(JSON 的作者),2012 年
【参考方案1】:
没有。
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 库支持 cmets。
如果我想对Accronym
和Abbrev
属性进行单独评论怎么办?我以前使用过这种模式,但由于它不允许我这样做而停止了。这是一个黑客。也许如果我在属性名称前加上__comment__
。那是“__comment__Abbrev”,仍然是一个 hack,但可以让我评论所有 prpoerties
你也可以使用“//”:这看起来更原生,并且仍然可以在同一个父级中重复
当 JSON 用于人为设计的配置文件时,应该对它们进行注释,以便人们更好地理解。注释,这样的文件不再是有效的 JSON,但是有解决方案。例如,Google 的 GYP 支持#-style cmets。 JSON.Minify 将帮助您从输入文件中丢弃 C/C++ 样式的 cmets。【参考方案2】:
否,在 JSON 中不允许使用 //…
或 /*…*/
形式的 cmets。此答案基于:
application/json
媒体类型
RFC 8259 JavaScript 对象表示法 (JSON) 数据交换格式(取代 RFC 4627、7158、7159)
【讨论】:
如果您想用 cmets 注释您的 JSON(从而使其无效 JSON),然后在解析或传输之前将其缩小。 Crockford 本人在 2012 年的配置文件中承认了这一点。 @alkuzad:当涉及到形式语法时,必须有明确说明它们是被允许的,而不是相反。例如,选择你的编程语言:仅仅因为某些期望(但缺少)的特性没有被明确禁止,并不意味着你的编译器会神奇地识别它。 是的。 JSON 格式在元素之间有很多死区,并且在这些区域中对空间不敏感,因此没有理由不能在那里使用单行或多行 cmets。许多解析器和压缩器也支持 JSON cmets,因此只需确保您的解析器支持它们。 JSON 大量用于应用程序数据和配置设置,因此现在需要 cmets。 “官方规范”是一个好主意,但它还不够且过时,太糟糕了。如果您担心负载大小或性能,请缩小 JSON。 虽然你的回答绝对正确,但应该说这是BS。由于有如此多的最终用户遇到对 json 配置的需求,因此 cmets 非常有用。仅仅因为一些锡箔帽子决定 JSON 是并且必须始终是机器可读的,而忽略了人类需要阅读它的事实,恕我直言,这是对狭隘思想的讽刺. @cmroanirgo:你显然不是第一个抱怨 JSON 的限制的人......这就是为什么我们有静默允许 cmets 和其他格式(如 YAML 和 JSON5)的解析器。然而,这并没有改变 JSON 就是这样的事实。相反,我觉得有趣的是,人们开始使用 JSON 的目的显然是不够的,因为存在问题。不要责怪 JSON 格式;责备自己坚持在不适合的地方使用它。【参考方案3】:如果您愿意,请包括 cmets;在解析或传输之前用压缩器将它们剥离。
我刚刚发布了 JSON.minify(),它从 JSON 块中去除 cmets 和空格,使其成为可以解析的有效 JSON。所以,你可以像这样使用它:
JSON.parse(JSON.minify(my_str));
当我发布它时,我遭到了很多人的强烈反对,甚至不同意它的想法,所以我决定写一篇全面的博客文章来解释为什么comments make sense in JSON。它包括来自 JSON 创建者的这条值得注意的评论:
假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有 cmets。然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。 - Douglas Crockford, 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 即使对于数据流(甚至数据包)使用,cmets 仍然有效:包含诊断元数据(如创建时间或源)在 XML 中很常见,对 JSON 非常明智数据也是如此。反对 cmets 的论据很肤浅,任何文本数据格式都应该允许 cmets,无论隐含的预期用途如何(没有规范建议 JSON 不能在其他地方使用,fwiw) 如果 JSON 要被普遍接受(它基本上是这样),那么它应该有普遍的应用。示例:JSON 可以用作应用程序配置文件。此应用程序需要 cmets。【参考方案4】:设计上已从 JSON 中删除评论。
我从 JSON 中删除了 cmets,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少 cmets 会让一些人感到难过,但它不应该。
假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有 cmets。然后通过 JSMin 将其传递给 JSON 解析器。
来源:Public statement by Douglas Crockford on G+
【讨论】:
我认为 JSON 应该比 XML 更易于阅读?注释是为了便于阅读。 无论如何,你可能会很顽皮,在 JSON 中添加解析指令:"__directives":"#n#":"DateTime.Now", "validdate":"#n#" ... 看起来 YAML 是前进的方向... 个人意见:不允许 cmets 是蹩脚的。除了构建一个忽略 cmets 的非标准 JSON 解析器来解码我的配置文件之外,我别无选择。 “我从 JSON 中删除了 cmets,因为我看到人们使用它们来保存解析指令”。按照这个逻辑,他也应该删除字符串类型。糟糕的决定。 这就像要求所有的自行车都有辅助轮,因为有些人不会骑自行车。因为愚蠢的人滥用它而删除一个重要功能是糟糕的设计。数据格式应该优先考虑可用性而不是白痴。【参考方案5】:JSON 不支持 cmets。它也从未打算用于需要 cmets 的配置文件。
Hjson 是人类的配置文件格式。轻松的语法,更少的错误,更多的 cmets。
有关 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(实际上不要:***.com/questions/450399/…)或坚持使用粗鲁但明确的 JSON。 我发现最人性化的配置格式还是INI。它很简单,而且语法不是很重。这使得用户只需将脚趾伸入配置池中就不会那么令人生畏了。 当你需要 json 作为配置时(需要 cmets 是) - 将你的文件命名为“.js”而不是“.json”.. js 当然可以处理任何有效的json 对象,另外 can 处理 cmets.. 这就是为什么它是“webpack.config.js”而不是“webpack.config.json”的原因(在 webpack 中也有更多的原因:P)【参考方案6】:免责声明:您的保修无效
正如已经指出的那样,这个 hack 利用了规范的实现。并非所有 JSON 解析器都能理解这种 JSON。流解析器尤其会窒息。
这是一个有趣的好奇心,但你根本不应该将它用于任何事情。以下是原答案。
我发现了一个小技巧,可让您将 cmets 放入 JSON 文件中,不会影响解析或以任何方式更改所表示的数据。
似乎在声明对象字面量时,您可以使用相同的键指定两个值,并且最后一个优先。信不信由你,事实证明 JSON 解析器的工作方式相同。因此,我们可以使用它在源 JSON 中创建不会出现在已解析对象表示中的 cmets。
(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]
这意味着没有cmets的踪迹,它们不会有奇怪的副作用。
黑客愉快!
【讨论】:
来自the specification:对象中的名称应该是唯一的。 不保证 JSON 中元素的顺序。这意味着“最后一个”项目可能会改变! 这显然违反了规范(见上面的 cmets),不要这样做。 ietf.org/rfc/rfc4627.txt?number=4627 NO - 如果解析器正在流式传输怎么办?如果解析器将其读入未定义键顺序的字典中怎么办? 用火杀死它。 由于我们一直在 JSON 工作组的 IETF 研究 RFC 4627bis(加入我们并提供帮助!datatracker.ietf.org/wg/json),我们发现了实现者用于重复名称的四种不同方法一个对象:使用第一个;使用最后一个;报告所有这些,让来电者选择一个;返回错误并停止解析。如果您的数据无法在所有这些方法中存活下来,那么它在实践中就无法互操作。【参考方案7】:考虑使用 YAML。它几乎是 JSON 的超集(实际上所有有效的 JSON 都是有效的 YAML)并且它允许 cmets。
【讨论】:
@NateS 很多人已经指出答案是否定的。我提出了一种更好的方法来实现 OP 的目标。这就是答案。 @marnen-laibow-koser:是的,为 Java 和 Perl 使用可用的 YAML 库并期望每个生成的 YAML 被另一个无错误地使用肯定是无能的。 YAML 互操作是一个问题,但 JSON 互操作不是,这完全是由于我缺乏知识。 @marnen-laibow-koser,用更简单的规范完成同样事情的格式更好。具有完美实现的实用格式优于具有不完美实现的理想格式。并非所有错误库的责任都在实施者的肩上。 YAML 规范冗长、密集且迟钝。它的***条目引用了两个模棱两可的例子;如果必须在人类和格式之间放置一个发射器以保护他们免受歧义,那么格式就失去了对人类友好的主张。 JSON 声明较少且大部分成功,而 YAML 声明较多且不足。 @marnen-laibow-koser,我已经驳斥了你对我自己无能的暗示,用细节支持我的主张,并稍微详细说明了我的偏好/偏见,这些偏好/偏见会影响我的 YAML 批评。我自己进一步的 cmets 可能收益递减。我对未来读者做出明智选择的能力充满信心。除了避开人身攻击之外,感谢您的演讲。如果您愿意,最后一个字是您的。 @toolbear 无意进行人身攻击。 “具有完美实现的实用格式优于具有不完美实现的理想格式”——我不确定我是否同意。如果格式是理想的(并且可以实现),那么人们总是可以制作一个好的实现。如果格式不理想,那么即使是完美的实现也不会很好。 :) “YAML 规范很长、很密集、很钝”——这实际上不是“钝”的意思,但是 YAML 规范很清楚。我没有看到***中提到的任何歧义;如果我遗漏了什么,请引用文章的特定部分。【参考方案8】:你不能。至少这是我快速浏览json.org的经验。
JSON 的语法在该页面上可视化。没有任何关于 cmets 的注释。
【讨论】:
【参考方案9】:注释不是官方标准,尽管一些解析器支持 C++ 风格的 cmets。我使用的是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 不验证这一点。所以 cmets 是特定于解析器的扩展,而不是标准的。
另一个解析器是JSON5。
JSON TOML 的替代品。
另一种选择是jsonc。
nlohmann/json 的最新版本具有在解析时忽略 cmets 的可选支持。
【讨论】:
Groovy 有一些 built-in classes for handling JSON。 JsonSlurper 可以处理 cmets。当然,官方规范中不允许使用 cmets,因此任何解析器中的这种行为都是非标准且不可移植的。 Newtonsoft Json.NET 也毫无问题地支持 C 风格的 cmets 恕我直言,这是该问题的最佳答案,因为它包含了许多确实支持的替代解析器的良好列表。不应鼓励使用重复或无关密钥的黑客行为,如果您想要/需要 cmets,您应该使用替代标准。【参考方案10】:你应该写一个JSON schema。 JSON 模式目前是一个提议的 Internet 草案规范。除了文档之外,该模式还可用于验证您的 JSON 数据。
例子:
"description":"A person",
"type":"object",
"properties":
"name":
"type":"string"
,
"age":
"type":"integer",
"maximum":125
您可以使用 description 架构属性提供文档。
【讨论】:
是的,json-schema google group 相当活跃,我会推荐JSV 用于 JSON Schema 验证器的良好 JavaScript 实现。 如果你使用 clojure(我相信你没有),这里有一个功能合理的开源 JSON 模式解析器:github.com/bigmlcom/closchema @Munhitsu Manatee.Json (.Net) 广泛支持 JSON 模式。 这并不适用于所有情况。我有一个手动配置的 JSON 以由具有自己架构的其他东西(包管理器)解析。因为我想要一个评论,例如 /* 最好使用 X 来代替另一个包管理器,但是那个管理器还没有提供 X。 */.【参考方案11】:如果您使用Jackson 作为您的 JSON 解析器,那么这就是您启用它以允许 cmets 的方式:
ObjectMapper mapper = new ObjectMapper().configure(Feature.ALLOW_COMMENTS, true);
那么你可以有这样的cmets:
key: "value" // Comment
您还可以通过设置使 cmets 以 #
开头:
mapper.configure(Feature.ALLOW_YAML_COMMENTS, true);
但总的来说(如前所述)规范不允许使用 cmets。
【讨论】:
这是可逆的吗?如果您加载文件并将其写回怎么办?【参考方案12】:这是我在Google Firebase documentation 中发现的,它允许您将 cmets 放入 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 中这样做 此方法破坏了一些要求密钥必须唯一的库。我正在通过给 cmets 编号来解决这个问题。 好评论,我在 SO 上发现了这个问题......这部分似乎没有被规范 ***.com/questions/21832701/… 我现在倾向于这样使用它: "//foo": "foo comment", "foo": "foo value", "//bar": "bar comment", " bar": "bar value" 你可以为多个 cmets 使用一个数组: "//foo": [ "foo comment 1", "foo comment 2" ], "foo": ''foo value" 跨度> 【参考方案13】:否。 JSON 曾经支持 cmets,但它们被滥用并从标准中删除。
来自 JSON 的创建者:
我从 JSON 中删除了 cmets,因为我看到人们使用它们来保存解析指令,这种做法会破坏互操作性。我知道缺少 cmets 会让一些人感到难过,但事实并非如此。 - Douglas Crockford, 2012
官方 JSON 网站位于 JSON.org。 JSON 被 ECMA International 定义为standard。总是有一个请求过程来修改标准。出于多种原因,不太可能将注释添加到 JSON 标准中。
JSON 在设计上是一种易于逆向工程(人工解析)的 XML 替代方案。它甚至被简化到不需要注释的地步。它甚至不是一种标记语言。目标是稳定性和互操作性。
任何理解面向对象的“具有”关系的人都可以理解任何 JSON 结构——这就是重点。它只是一个带有节点标签(键/值对)的有向无环图(DAG),是一种近乎通用的数据结构。
唯一需要的注释可能是“//这些是 DAG 标记”。键名可以根据需要提供信息,允许任意语义。
任何平台都可以只用几行代码解析 JSON。 XML 需要复杂的 OO 库,而这些库在许多平台上都不可行。
注解只会降低 JSON 的互操作性。没有什么可添加的,除非您真正需要的是一种标记语言 (XML),并且不在乎您的持久数据是否易于解析。
但是正如 JSON 的创建者也观察到的那样,一直有对 cmets 的 JS 管道支持:
继续插入所有你喜欢的 cmets。 然后通过 JSMin 将其通过管道传递给您的 JSON 解析器。 - Douglas Crockford, 2012
【讨论】:
【参考方案14】:如果您使用带有 ASP.NET 的 Newtonsoft.Json 库来读取/反序列化,您可以在 JSON 内容中使用 cmets:
//“名称”:“字符串”
//"id": int
或
/* 这是一个
评论示例 */
PS:单行 cmets 仅支持 6+ 版本的 Newtonsoft Json。
对无法跳出框框思考的人的补充说明:我在我制作的 ASP.NET Web 应用程序中使用 JSON 格式进行基本设置。我读了文件,用 Newtonsoft 库将它转换为设置对象,并在必要时使用它。
我更喜欢为 JSON 文件本身中的每个单独设置编写 cmets,而且我真的不关心 JSON 格式的完整性,只要我使用的库可以接受它。
我认为这是一种“更易于使用/理解”的方式,而不是创建单独的“settings.README”文件并解释其中的设置。
如果您对这种用法有疑问;对不起,精灵不在灯里了。人们会发现 JSON 格式的其他用途,而您对此无能为力。
【讨论】:
很难理解为什么有人在陈述事实时会有问题。 我会假设有人例外,因为上面不再是 JSON,或者是无效的 JSON。也许添加一个简短的免责声明会安抚。 我完全同意你的观点,但到目前为止,有 883 人赞成不回答,只是说明了这一点。意识形态的纯洁性高于有用的信息,对你来说就是这样。 重点是带有cmets的文件不是JSON,很多JSON库都会解析失败。随意在自己的程序中做任何你想做的事情,但带有 cmets 的文件不是 JSON。如果您声称它是,那么人们将尝试用他们选择的语言/库来解析它,它会失败。这就像问是否可以在 XML 中使用方括号代替尖括号。你可以做任何你想做的事,但它不再是 XML。【参考方案15】:如果您的文本文件是一个 JSON 字符串,将被某个程序读取,那么在使用之前去除 C 或 C++ 样式的 cmets 会有多困难?
答案:这将是一个单一的班轮。如果你这样做,那么 JSON 文件可以用作配置文件。
【讨论】:
可能是目前为止最好的建议,尽管将文件保留为交换格式仍然是一个问题,因为它们需要在使用前进行预处理。 我同意并用 Java 编写了一个 JSON 解析器,可以从 www.SoftwareMonkey.org 获得,它就是这样做的。 尽管我认为,扩展 JSON 不是一个好主意(不称其为不同的交换格式):确保忽略字符串中的“cmets”。 "foo": "/* 这不是评论。*/" "...将是一个单行" 嗯,不,实际上,JSON 不是正则表达式可以简单地找到匹配的 /* 对的正则语法。您必须解析文件以查找 /* 是否出现在字符串中(并忽略它),或者它是否被转义(并忽略它)等。此外,您的答案没有帮助,因为您只是推测(错误地)而不是提供任何解决方案。 @kyle-simpson 说了什么。此外,他过于谦虚,无法将读者引导到他自己关于使用 JSON.minify 作为临时正则表达式的替代方案的答案。做那个,而不是这个。【参考方案16】:JSON 背后的理念是在应用程序之间提供简单的数据交换。这些通常是基于网络的,语言是 JavaScript。
它实际上并不允许这样的 cmets,但是,将注释作为数据中的名称/值对之一传递肯定会起作用,尽管该数据显然需要被解析代码忽略或专门处理.
综上所述,JSON 文件不应该包含传统意义上的 cmets。它应该只是数据。
查看JSON website 了解更多详情。
【讨论】:
JSON格式确实没有cmets。我个人认为这是一个重大错误——将 cmets 作为元数据(而不是数据)的能力对于 xml 非常有用。 JSON 规范的早期草案版本确实包含 cmets,但由于某种原因,它们被删除了。 :-/ @StaxMan 它们被删除的原因正是因为人们开始将它们用作元数据。 Crockford 说它破坏了格式设计的兼容性,我同意:如果您想要元数据,为什么不将其作为实际数据包含在内?这种方式解析起来更加容易。 元数据属于元数据结构(例如 html 标签),而不是 cmets。滥用 cmets 获取元数据只是在不存在真正的元数据构造的情况下使用的一种技巧。 这正是它被删除的原因:用作元数据的 cmets 会破坏互操作性。您也应该将元数据存储为 JSON。【参考方案17】:JSON 本身不支持 cmets,但您可以制作自己的解码器或至少预处理器来去除 cmets,这非常好(只要您忽略 cmets 并且不使用它们来指导您的应用程序应该如何处理JSON 数据)。
JSON 没有 cmets。 JSON 编码器不得输出 cmets。 JSON 解码器可以接受和忽略 cmets。
评论不应该被用来传递任何有意义的东西。那是 JSON 的用途。
参考:Douglas Crockford, author of JSON spec.
【讨论】:
Crockford 后来继续写道:“假设您使用 JSON 来保存您想要注释的配置文件。继续插入您喜欢的所有 cmets。然后通过 JSMin 管道将其传递给它到你的 JSON 解析器。”有关更多信息,请参阅@kyle-simpson 关于 JSON.minify 的回答。【参考方案18】:我只是在配置文件中遇到了这个问题。我不想使用 XML(冗长、图形化、丑陋、难以阅读)或“ini”格式(没有层次结构、没有真正的标准等)或 Java“Properties”格式(像.ini)。
JSON 可以做他们能做的所有事情,但它不那么冗长,而且更易于阅读——而且解析器在许多语言中都很简单且无处不在。它只是一棵数据树。但是带外 cmets 通常是记录“默认”配置等的必要条件。配置永远不会是“完整文档”,而是在需要时可供人类阅读的已保存数据树。
我想可以使用"#": "comment"
,作为“有效”JSON。
【讨论】:
对于配置文件,我建议使用 YAML,而不是 JSON。它(几乎)是更强大的 JSON 超集,但也支持更易读的结构,包括 cmets。 @Hamidam 十多种语言支持 yaml:yaml.org - 但您可以问有多少支持内置,而不需要第三方库依赖项。看起来像 Ruby 1.9.2 一样。有人知道其他人吗?哪些语言默认支持 json? YAML 互操作是个谎言:***.com/questions/450399/…。如果您的直觉是将 JSON 用于配置文件,请遵循它。 这是旧的,但我相信使用 # 不是一个好主意。 Json 接近于 Javascript 文字的语法。 Javascript 支持两种类型的注释: // 和 /* ... */ 如果我是你,我会坚持使用这两种类型的 cmets 中的一种或两种。【参考方案19】:这取决于您的 JSON 库。 Json.NET 支持 JavaScript 样式的 cmets,/* commment */
。
见another Stack Overflow question。
【讨论】:
我相信这就是为什么我在这个 ASP.NET vNext 预览页面(在 package.json 下)的屏幕截图中看到评论的原因:blogs.msdn.com/b/webdev/archive/2014/06/03/… 尽管我还没有在规范中找到任何内容.【参考方案20】:JSON 对于配置文件和其他本地使用很有意义,因为它无处不在,而且比 XML 简单得多。
如果人们在传输数据(无论是否有效)时有充分的理由反对在 JSON 中使用 cmets,那么 JSON 可能会一分为二:
JSON-COM:在线上的 JSON,或传输 JSON 数据时应用的规则。 JSON-DOC:JSON 文档,或文件中或本地的 JSON。定义有效 JSON 文档的规则。JSON-DOC 将允许 cmets,并且可能存在其他细微差异,例如处理空格。解析器可以轻松地从一种规范转换为另一种规范。
关于 Douglas Crockford 在此问题上提出的remark(@Artur Czajka 引用)
假设您使用 JSON 来保存您想要注释的配置文件。继续并插入您喜欢的所有 cmets。然后通过 JSMin 将其传递给 JSON 解析器。
我们正在讨论一个通用配置文件问题(跨语言/平台),而他正在回答一个 JS 特定实用程序!
确定 JSON 特定的缩小可以用任何语言实现, 但是将其标准化,使其在所有语言和平台的解析器中无处不在,因此人们不再浪费时间缺乏该功能,因为他们有很好的用例,在在线论坛中查找问题,并让人们告诉他们这是一个坏主意或建议很容易实现从文本文件中剥离 cmets。
另一个问题是互操作性。假设您有一个库或 API 或任何类型的子系统,其中包含一些与之关联的配置或数据文件。这个子系统是 可以从不同的语言访问。然后你会告诉人们:顺便说一句 在将它们传递给解析器之前,不要忘记从 JSON 文件中去除 cmets!
【讨论】:
无需对 JSON 进行分段。带有 cmets 的 JSON 不再是 JSON。但是用 cmets 注释你的 JSON 是完全可以接受的,只要你确保在解析或传输它之前去掉它们。这样做绝不应该是接收者的责任。【参考方案21】:如果您使用JSON5,则可以包含 cmets。
JSON5 是 JSON 的提议扩展,旨在使人类更容易手动编写和维护。它通过直接从 ECMAScript 5 添加一些最小的语法特性来做到这一点。
【讨论】:
你能添加一个例子吗?那么你可能真的需要那些额外的字符。 SO 指南要求提供实际答案。不需要仅链接的答案。您可以查看指南***.com/help/how-to-answer SO 由其用户管理。这意味着如果我有答案,我可以提供答案,如果它不遵循指导方针,我可以评论你的答案。这就是 SO 成为优秀资源的原因。【参考方案22】:Dojo Toolkit JavaScript 工具包(至少从 1.4 版开始)允许您在 JSON 中包含 cmets。 cmets 可以是/* */
格式。 Dojo Toolkit 通过 dojo.xhrGet()
调用使用 JSON。
其他 JavaScript 工具包的工作方式可能类似。
在选择最终选项之前尝试替代数据结构(甚至数据列表)时,这会很有帮助。
【讨论】:
没有。不是这个。 JSON 没有 cmets。如果您选择使用 cmets 注释您的 JSON,请在解析或传输之前将其缩小。这不应该是接收者的责任。 我没有说 JSON 有 cmets。我也不是暗示将它们包含在您的 JSON 中是合适的,尤其是在生产系统中。我说过 Dojo 工具包 允许您添加它们,这是(或至少是)事实上是正确的。在您的测试阶段有非常有用的用例。 提供评论是一种糟糕的巫术,因此 JSON 无效,dojo.xhrGet()
通过接受隐含鼓励。
我仍然投票支持升级 JSON 规范以允许 cmets。我完全赞成在传输 JSON 之前缩小和剥离 cmets,但没有任何能力以任何标准方式评论您的 JSON,而不必在解析它之前通过单独的实用程序传递它,这似乎很愚蠢。我还让您无法在 JSON 配置文件上使用 JSON 编辑器,因为您的文件不是有效的 JSON。【参考方案23】:
是的,新标准,JSON5 允许 C++ 样式的 cmets,在众多 other extensions 中:
// A single line comment.
/* A multi-
line comment. */
JSON5 数据交换格式 (JSON5) 是 JSON 的超集,旨在缓解 JSON 的一些限制。它完全向后兼容,并且使用它可能比编写自定义非标准解析器、为现有解析器打开非标准功能或使用各种技巧(如字符串字段进行注释)更好。或者,如果使用的解析器支持,只需同意我们使用的是 JSON 5 子集,即 JSON 和 C++ 样式的 cmets。它比我们以我们认为合适的方式调整 JSON 标准要好得多。
已经有npm package、Python package、Java package 和C library 可用。它向后兼容。我认为没有理由继续遵守“官方”JSON 限制。
我认为从 JSON 中删除 cmets 的原因与在 Java 中删除运算符重载的原因相同:可能会以错误的方式使用,但忽略了一些明显合法的用例。对于运算符重载,它是矩阵代数和复数。对于 JSON cmets,它是可以由人类编写、编辑或读取的配置文件和其他文档,而不仅仅是解析器。
【讨论】:
JSON5“非常”标准吗?还是还在被收养?我的意思是……我可以期望 2021 年的任何框架都能理解 Json5 吗?或者很可能不是? 如果您创建自己的标准,那么您是世界上唯一使用它的人。像 JSON5 这样的东西可能更好。 并不是要创建我的标准...只是想知道是时候考虑 JSON5 还是更好地坚持“旧 JSON”,然后再等几个月再花时间进行探索。 JSON5 不是“新标准”——它是由不同的人开发的独立标准。【参考方案24】:JSON 不是框架协议。它是一种无语言格式。所以评论的格式没有为 JSON 定义。
正如许多人所建议的,您可以使用一些技巧,例如重复键或特定键_comment
。这取决于你。
【讨论】:
【参考方案25】:免责声明:这很愚蠢
实际上有一种方法可以添加 cmets,并保持在规范范围内(不需要额外的解析器)。但是,如果没有任何类型的解析,它不会产生人类可读的 cmets。
您可能会滥用以下内容:
在任何标记之前或之后都允许有无关紧要的空格。 空格是以下一个或多个代码的任何序列 要点:字符制表(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
(hello base three
in ASCII) 但不是 0 使用空格,1 使用换行,2 使用回车。
这只会给你留下很多不可读的空白(除非你制作一个 IDE 插件来即时对其进行编码/解码)。
出于显而易见的原因,我什至从未尝试过,你也不应该这样做。
【讨论】:
这很有趣。【参考方案26】:这是一个“你能不能”问题。这是一个“是”的答案。
不,您不应该使用重复的对象成员将侧通道数据填充到 JSON 编码中。 (请参阅“对象中的名称应该是唯一的”in the RFC)。
是的,你可以insert comments around the JSON,你可以解析出来。
但是,如果您想要一种将任意侧通道数据插入和提取到有效 JSON 的方法,这里有一个答案。我们利用 JSON 编码中数据的非唯一表示。这在 RFC 的第二部分中允许*“在六个结构字符中的任何一个之前或之后允许空白”。
*RFC 仅规定“在六个结构字符之前或之后允许有空格”,没有明确提及字符串、数字、“false”、“true”和“空值”。在所有实现中都会忽略此省略。
首先,通过缩小 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”表示定义是规范的绝对要求。 ...应该:这个词,或形容词“推荐”,意味着在特定情况下可能存在忽略特定项目的正当理由,但在选择不同的课程之前,必须理解并仔细权衡全部含义。 很好的参考。反对使用重复键的更好理由是标准的引用“当对象中的名称不唯一时,接收此类对象的软件的行为是不可预测的。”。现在我也明白了为什么标准不是“必须是唯一的”,这使得验证器更简单,它只需要跟踪 [ 和 ,它不需要知道已经使用了哪些键。【参考方案27】:您可以在JSONP 中有 cmets,但不能在纯 JSON 中。我刚刚花了一个小时试图让我的程序使用来自 Highcharts 的这个示例:http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-c.json&callback=?
如果你点击链接,你会看到
?(/* 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
由于 cmets 默默地失败了。
最后我只是向上面的地址发送了一个手动 HTTP 请求,并意识到内容类型是 text/javascript
,因为 JSONP 返回纯 JavaScript。在这种情况下,cmets 是允许的。但是我的应用程序返回了 content-type application/json
,所以我不得不删除 cmets。
【讨论】:
【参考方案28】:JSON 本身不允许 cmets。推理是完全愚蠢的,因为您可以使用 JSON 本身来创建 cmets,这完全排除了推理,并且完全没有理由加载解析器数据空间 em>完全相同的结果和潜在问题,例如:带有 cmets 的 JSON 文件。
如果您尝试将 cmets 放入(例如使用
//
或/* */
或#
),那么某些解析器将失败,因为这绝对不是 在 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."
【讨论】:
“推理”链接已损坏。有没有机会找到它的当前链接? 唐,不幸的是,谷歌已经杀死了包含该帖子的社交媒体系统;我不知道原始海报从那里去哪里,如果在任何地方。不过,我将删除上述信息中的链接,以消除歧义。谢谢。 这个推理不是愚蠢的,你刚刚证明了这一点。将 cmets 实现为标签保留了互操作性。这正是 Crockford 希望将 cmets 解析为标签的原因。现在 everything 只是一个标签,并以 相同的方式解析。 如果规范声明“以 # 开头的行是注释”,那么这将是完全可互操作的。就目前而言,cmets 都加载解析器空间,如它们是有效的已解析项,而不是被理解为 cmets,并且它们对于存在的每个 .json 文件都可能不同。然而,如果(例如)规范说“以 # 开头的行是 cmets”,那么解析器可以跳过这些行而不进行解析(更快)并且不加载解析器空间(更好的内存利用率。)缺乏没有任何好处.json 中的 cmets,只有缺点。【参考方案29】:就我而言,我需要在输出 JSON 之前使用 cmets 进行调试。所以我把调试信息放在HTTP header中,避免破坏客户端:
header("My-Json-Comment: Yes, I know it's a workaround ;-) ");
【讨论】:
【参考方案30】:我们的项目使用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
包含这些专有 cmets 时,它不再是有效的 JSON。
strip-json-cmets 在什么上下文中运行? Node.js?
@PeterMortensen 我尝试了 node.js。您可以尝试是否适用于客户端js。以上是关于可以在 JSON 中使用注释吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 PHP 解码带有注释的 JSON 文件? [复制]