【问题标题】:In YAML, must a quoted scalar be interpreted by a parser as a string?在 YAML 中,解析器必须将带引号的标量解释为字符串吗?
【发布时间】:2018-09-28 02:07:09
【问题描述】:

我在 Internet 上看到过一些建议,如果您希望将 YAML 标量值作为字符串处理,您应该引用它:

foo : "2018-04-17"

在上面的示例中,此建议旨在告诉我值 2018-04-17 将由任何给定的 YAML 解析器作为其本地语言的字符串类型处理。例如,SnakeYAML 将在此建议为真时将其解释为java.lang.String,而不是java.util.Date。 (碰巧,SnakeYAML 将其解释为 java.util.Date,引号或不引号,这就是我问这个问题的原因。)

但是,尽管这个建议可能发生与任何给定的解析器一起工作,我看不出YAML 1.2. specification这个建议可能来自哪里。我能找到的最接近的是the following sentence

YAML 允许标量以多种格式呈现。例如,整数“11”也可以写成“0xB”。标签必须指定将格式化内容转换为规范形式以用于相等性测试的机制。与节点样式一样,格式是表示细节,不会反映在序列化树和表示图中。

还有this one:

标量样式是一种表示细节,不得用于传达内容信息,除非为了标记解析目的而区分普通标量。

还有this one

注意分辨率一定不能考虑cmets、缩进、节点样式等表现细节。

尽管如此,我看到很多 YAML 文档都依赖于双引号的值意味着它会被解析为字符串的建议,这让我觉得我误读了一些东西。这个问题有争议吗?

【问题讨论】:

    标签: yaml snakeyaml


    【解决方案1】:

    YAML 1.1 规范中的相关部分(请注意,SnakeYaml 是 YAML 1.1,因此 1.2 规范不一定适用):

    不需要在字符流中明确指定完整表示的所有标签。在解析过程中,省略标签的节点被赋予一个非特定标签:“?”对于普通标量和“!”对于所有其他节点。 [...]

    建议节点带有“!”非特定标签应根据节点类型解析为“tag:yaml.org,2002:seq”、“tag:yaml.org,2002:map”或“tag:yaml.org,2002:str”。此约定允许 YAML 字符流的作者对标签解析过程施加一定程度的控制。通过显式指定一个普通标量具有“!”非特定标签,节点被解析为字符串,就好像它被引用或以块样式写入一样。但是请注意,每个应用程序都可能会覆盖此行为。例如,应用程序可能会自动检测源代码中使用的编程语言类型,以非纯标量形式呈现并相应地对其进行解析。

    总而言之,YAML 处理器不需要 将引用的标量解析为字符串,并且 YAML 也没有规定 tag:yaml.org,2002:str 映射到哪个本机类型。事实上,大多数 YAML 实现只遵循该建议的一部分。例如,如果您使用 SnakeYaml 将 YAML 反序列化为 POJO/JavaBean,您通常不会在 YAML 中使用任何显式标记,但您的映射将解析为根类结构中的相应 Java 类,而不是通用的 @987654322 @ 这就是这个建议所建议的(因为所有没有显式标签的映射都会得到 ! 非特定标签)。

    请注意,这已在 YAML 1.2 中更改:

    在解析过程中,缺少显式标记的节点会被赋予一个非特定标记:“!”对于非普通标量和“?”对于所有其他节点。

    这更接近于大多数实现,但例如,如果你反序列化为一个类 class Foo { String bar; },尽管 bar 不是字符串,而是字段名称,它仍然会加载:

    "bar": some value
    

    所以使用 YAML 的建议是在应用程序端指定所需的结构 - 在 SnakeYaml 中,您将设置根类类型,然后每个值将在层次结构中的点映射到所需的类型,如只要它能够映射到那里,无论它是否被引用或未引用。一般来说,应用程序指定它在整个层次结构中期望的值类型更有意义,而不是 YAML 作者通过引用来做到这一点。这也符合 YAML 规范,其中说

    解析一个节点的标签必须只依赖以下三个参数:(1)节点的非特定标签,(2)从根到节点的路径,(3)内容(以及节点的类型)。

    解析标签是用于确定目标类型的 YAML 术语。并且允许根据其在层次结构中的位置来确定目标类型:根类型由元素是 YAML 文档的根这一事实确定,在 SnakeYaml 的情况下,可以通过 API 输入。所有其他类型都由它们是根类型的后代这一事实决定。

    最后说明:如果你真的想要某个字符串是一个字符串,!!str 2018-04-17 可以,因为它为节点设置了一个特定的标签。

    【讨论】:

    • 谢谢。所以它本质上就像我想的那样:解析器可以以多种不同的方式解析未标记(标量)YAML,而不管引用样式如何。在这种情况下,我无法控制 (a) 源文档或 (b) 解析器,所以这会变得很有趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多