TOML与YAML与StrictYAML

TOML 说: “TOML 和 YAML 都强调人类可读性特征,例如注释可以更容易地理解给定行的目的。TOML 在组合这些方面有所不同,允许注释(与 JSON 不同)但保留简单性(与 YAML 不同)。”

我可以看到 TOML 不依赖重要的空格,但除此之外,我不确定它声称的 简单性。那究竟是什么?

然后我看到StrictYAML,“StrictYAML 是一个类型安全的 YAML 解析器,它解析和验证 YAML 规范的一个受限子集。” 类型安全,那到底是什么(再次)?TOML 没有为 YAML 修复而 StrictYAML 认为他有什么问题?我确实阅读了 StrictYAML 网站上的文章,但我仍然不清楚。

所以 TOML 和 StrictYAML 都想解决 YAML 的“问题”。但是除了缩进,还有什么问题?

- - 更新 - -

我在 reddit 上发现 StrictYaml 的作者谈到了YAML 与 TOML。但到目前为止我得到的答案是“strictyaml 显示对 YAML 的理解相当差”

YAML 的缺点:

隐式类型会导致意外的类型更改。(例如,把 3 放在你之前有一个字符串的地方,它会神奇地变成一个 int)。

一堆令人讨厌的“隐藏功能”,例如节点锚点和引用,使其看起来不清楚(尽管公平地说,很多人不使用它)。

TOML的缺点:

更嘈杂的语法(尤其是多行字符串)。

数组/表的处理方式令人困惑,尤其是表数组。

我写了一个库,它删除了我不喜欢 YAML 的大部分讨厌的东西,留下了我喜欢的核心。它与一堆其他配置格式之间进行了非常详细的比较,例如:https : //github.com/crdoconnor/strictyaml/blob/master/FAQ.rst#why-not-use-toml

回答

这可能是一个固执的答案,因为我已经编写了多个 YAML 实现。


替代方案解决了对 YAML 的常见批评

YAML 突出的语义特征是它可以表示一个可能的循环图。此外,YAML 映射可以使用复杂节点(序列或映射)作为键。当您想要表示任意数据结构时,这些功能是您可能需要的。

另一个奇特的 YAML 功能是tags。他们的目标是抽象不同编程语言中的不同类型,例如,!!mapadict在 Python 中是 a而object在 JavaScript 中是 a 。虽然很少显式使用,但隐式标签解析是为什么false通常作为布尔值droggeljug加载而作为字符串加载的原因。这里的明显目标是通过不需要!!bool false在每个字符串值上写入布尔值或强制引号来减少噪音。

然而,现实表明很多人对此感到困惑,而 YAML 定义的yes可能被解析为布尔值也无济于事。YAML 1.2 试图通过描述您可以使用的不同模式来解决这个问题,其中基本的“故障安全”模式专门加载到映射、序列和字符串,而更复杂的“JSON”和“核心”模式进行额外的类型猜测。然而,大多数 YAML 实现,尤其是 PyYAML,在 YAML 1.1 上保留了很长时间(许多实现最初是重写 PyYAML 代码,例如 libyaml、SnakeYAML)。这巩固了 YAML 做出需要修复的有问题的类型决策的观点。

如今,一些实现得到了改进,您可以使用故障安全模式来避免不需要的布尔值。在这方面,StrictYAML 将自身限制为故障安全模式;不要相信它的论点,即这是 PyYAML 无法做到的一些新奇事物。

YAML 实现的一个常见安全问题是它们将标签映射到任意构造函数调用(您可以在此处阅读基于此的 Ruby on Rails 漏洞利用)。请注意,这不是 YAML 的缺点;YAML 不建议在任何地方的对象构造过程中调用未知函数。这里的基本问题是数据序列化是数据封装的敌人;如果您的编程语言提供构造函数作为构造对象的唯一方法,那么这就是您在反序列化数据时需要做的。这里的补救措施只是调用已知的构造函数,这是在一系列此类漏洞利用(另一个使用 SnakeYAML iirc)浮出水面之后广泛实施的。如今,要调用未知的构造函数,您需要使用DangerLoader在 PyYAML 中恰当命名的类。

TOML

TOML 的主要语义差异在于它不支持循环、复杂键或标签。这意味着虽然您可以在任意用户定义的类中加载 YAML,但您始终将 TOML 加载到包含数据的数组中。

例如,虽然YAML允许你加载{foo: 1, bar: 2}到一个类的对象foobar整型字段,TOML总是这样加载到一个表。您通常在文档中发现的 YAML 功能的一个突出示例是它可以将标量加载1d6到对象中{number: 1, sides: 6};TOML 将始终将其加载为 string "1d6"

TOML 在这里被认为的简单性是它不做 YAML 做的一些事情。例如,如果您使用静态类型语言(如 Java),则在加载{foo: 1, bar: 2}到对象后myObject,您可以myObject.foo安全地访问(获取整数1)。如果您使用了 TOML,则需要这样做myObject["foo"],,如果密钥不存在,则可能会引发异常。这在 Python 等脚本语言中不太正确:这里,myObject.foo如果foo不是myObject.

我在这里回答很多 YAML 问题的观点是,人们不使用 YAML 的功能,并且经常将所有内容加载到类似Map<String, Object>(以 Java 为例)的结构中,然后从那里获取。如果你这样做,你也可以使用 TOML。

TOML 提供了另一种简单的语法:由于它比 YAML 简单得多,因此更容易发出用户可以理解的错误。例如,YAML 语法错误中的常见错误文本是“在此上下文中不允许映射值”(尝试在 SO 上搜索以查找大量问题)。你在这里得到这个例子:

foo: 1
  bar: 2

错误消息不能帮助用户修复错误。这是因为 YAML 的复杂语法:YAML 认为1并且bar是多行标量的一部分(因为bar:缩进超过foo:),将它们放在一起,然后看到第二个:并失败,因为多行标量可能不会用作隐式键。然而,最有可能的是,用户要么是缩进的,要么是bar:认为他们可以给 foo ( 1) 和一些孩子一个标量值。由于 YAML 语法的可能性,很难编写可以帮助用户的错误消息。

由于 TOML 的语法要简单得多,因此错误消息更容易理解。如果编写 TOML 的用户不是具有语法分析背景的人,那么这是一个很大的优势。

TOML 比 YAML 有一个概念上的优势:由于它的结构允许较少的自由度,它往往更容易阅读。在阅读 TOML 时,您总是知道,“好吧,我将在其中包含带有值的嵌套表”,而使用 YAML,您有一些任意结构。我相信这在阅读 YAML 文件时需要更多的认知负荷。

严格的YAML

StrictYAML 认为它提供了类型安全性,但由于 YAML 不是一种编程语言,并且特别不支持赋值,因此基于由 StrictYAML 链接的维基百科定义,这种说法没有任何意义(类型安全性来使用您使用的编程语言;例如,任何 YAML 在将其加载到适当的 Java 类实例中后都是类型安全的,但在 Python 之类的语言中,您永远不会是类型安全的)。回顾其已删除功能列表,它显示对 YAML 的理解相当差:

  • 隐式类型:可以在 YAML 实现中使用故障安全模式停用,如上所述。
  • 对象的直接表示:它只是链接到 Ruby on Rails 事件,这意味着这是无法避免的,即使今天大多数实现在不删除该功能的情况下是安全的。
  • Duplicate Keys Disallowed:YAML 规范已经要求这样做。
  • Node anchors and refs:StrictYAML 认为使用它进行重复数据删除对于非程序员来说是不可读的,忽略了其意图是能够序列化循环结构,这在没有锚点和别名的情况下是不可能的。

在反序列化方面,

所有数据都是字符串、列表或 OrderedDict

它基本上与 TOML 支持的结构相同(我相信 StrictYAML 支持映射中的复杂键,因为在 Python 中既不能list也不能哈希OrderedDict)。

您还失去了反序列化为预定义类结构的能力。有人可能会说,由于无法构造一个类的对象具有良好定义的两个领域,因此StrictYAML较少类型安全比标准YAML:标准的YAML实现能保证返回的对象由类型描述一定的结构,而StrictYAML让你在每级别可以是字符串、列表或 OrderedDict 并且您不能做任何事情来限制它。

虽然它的一些论点有缺陷,但由此产生的语言仍然可用。例如,使用 StrictYAML,您无需关心困扰某些 YAML 实现的十亿笑声攻击。同样,这不是 YAML 问题而是实现问题,因为 YAML 不需要实现来复制从多个位置锚定和引用的节点。

底线

相当多的 YAML 问题源于糟糕的实现,而不是语言本身的问题。然而,YAML 作为一种语言肯定是复杂的,并且语法错误可能难以理解,这可能是使用像 TOML 这样的语言的正当理由。至于 StrictYAML,它确实提供了一些好处,但我建议不要使用它,因为它没有适当的规范,而且只有一个实现,这是一个很容易成为维护噩梦的设置(项目可能会中断,破坏更改很容易)。

  • @Qiulang I see indentation for structuring as interesting but ultimately flawed concept (not just for YAML, also for Python or Nim). Without a visible token that ends a structure, code gets more difficult to read the more nesting it has and the longer it is. While in Python you can restructure your code to battle excessive nesting, this is not really possible in YAML. However a similar argument has also been made for C's `}` (versus Pascal's `end <name>;`) and `}` is still used by most modern languages so it seems to be personal preference.
  • But at least TOML doesn't have this problem. Maybe that is one of reasons for its "simplicity"?

以上是TOML与YAML与StrictYAML的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>