哪些有效的JSON文件不是有效的YAML 1.1文件?

时间:2014-02-05 18:04:19

标签: json yaml

YAML 1.2(对于重复键有一个minor caveat)是JSON的超集,因此任何有效的JSON文件也是有效的YAML文件。但是,YAML 1.1 specificationlibrary support}最多)没有提到JSON。大多数有效的JSON文件都是有效的YAML 1.1文件,但我通过试验PyYaml和Python的标准JSON库发现了至少一个例外:

  • Python的JSON库将12345e999等双精度浮点溢出解释为PyYAML和IEEE infinity的字符串。

是否有人有完整的差异列表,比通过测试特定实现中的边缘案例更有力地确定? (也就是说,从规范的比较?)例如,我想生成JSON字符串,它们将由JSON解析器和YAML 1.1解析器以相同的方式解释:我必须在字符串上放置哪些约束?

2 个答案:

答案 0 :(得分:8)

here(特别是脚注25)。它说:

  

不兼容性如下:JSON允许扩展字符   像UTF-32一样设置并且具有不兼容的unicode字符转义语法   相对于YAML; YAML在逗号之类的分隔符之后需要一个空格,   等于,而冒号虽然JSON没有。有些不规范   JSON的实现扩展了语法以包含Javascript   /*...*/ 评论。处理这种边缘情况可能需要光线   在解析为内联YAML之前预处理JSON

另见https://metacpan.org/pod/JSON::XS#JSON-and-YAML

相关
What is the difference between YAML and JSON? When to prefer one over the other

答案 1 :(得分:2)

正如您所注意到的,有一件事是规范说明了其他常用解析器(YAML JSON)处理的内容。因此,您应该考虑几个方面,并使用最小公分母,以便无法使用YAML解析器加载JSON。

在JSON方面,有多种标准和最佳实践。最初,JSON文本必须在最顶层有一个对象或数组。根据{{​​3}}网站上提供的fail1.json文件,仍然如此:

"A JSON payload should be an object or array, not a string."

根据json.org,任何值都可以在顶层(除了使用字符串,这会导致相当无聊的JSON文件):

  

JSON文本是序列化值。注意某些先前的      JSON的规范将JSON文本约束为对象或      阵列。仅生成对象或数组的实现      调用的JSON文本在所有方面都是可互操作的      实现将接受这些作为符合JSON文本。

由于JSON劫持问题(通过重新定义旧浏览器中的数组),已经存在只接受顶层对象的实现(即文件的第一个字符必须是{

在YAML方面,与JSON相比,竞争标准较少,但YAML 1.1的持续使用使得事情变得混乱,并且如果你谷歌获得“yaml current spec”,那么第一次打击就是yaml .org / spec / current.html,这实际上是YAML 1.1 工作草案

除了UTF-32支持之外,提到的另一个答案,在一个几乎完全使用UTF-8的世界中基本上没有问题,有一些事情需要考虑,特别是如果你想让PyYAML成为能够解析你的JSON(PyYAML仍然只实现了大部分的YAML 1.1,接近YAML 1.2规范发布后的八年):

  • JSON中的数字在尾数中不需要一个点,即使这样的数字有一个指数:

    RFC7159

    enter image description here确实需要点:

    |[-]?0\.([0-9]*[1-9])?e[-+](0|[1-9][0-9]+) (scientific)
           ^--- no ? or * associated with this dot
    

    (在YAML 1.2规范中,此正则表达式已更改为:

    -? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?.
    

    即使有e(并且没有E)和指数,也允许点消失。

    这是12345e999被JSON(溢出)和PyYAML(字符串)处理的原因。在YAML 1.1中,这只能被解释为一个字符串,因此不会需要引号并且可以是普通标量。

  • 在YAML 1.1中有转义序列,但这不是JSON支持的超集。正斜杠(/)可以在JSON中转义,但不能在Floating-Point Language-Independent Type for YAML™ Version 1.1中转义(它可以在YAML 1.1,规则53中)

  • 在JSON和YAML 1.1中,您可以使用\uNNNN来指示16位的unicode代码点。虽然YAML 1.1规范(和YAML 1.2)在使用UTF-16时提到了代理对,但没有提到关于这些对作为转义序列("\uD834\uDD1E")。此字符串序列在RFC 7159中明确提及为表示G谱号字符(U + 1D11E)。我不知道任何支持它的YAML解析器,PyYAML会抛出:

      

    yaml.reader.ReaderError:不可接受的字符#xd834:不允许使用特殊字符

只要你写下你的JSON

  • 为UTF-8
  • 以顶级为对象
  • 科学数字总是带点<​​/ li>
  • 没有\/转义序列
  • \uNNNN\uD7FF之间没有\uE000个字符(不包括),\uFFFE也不\uFFFF

你应该对JSON和YAML(1.1)解析器都没问题。

¹YAML 1.2我作为作者的YAML 1.2解析器中,正确处理\/和没有点的科学数字:12345e999加载为float类型{{ 1}}并打印为inf