首页 > 解决方案 > 这是一个有效的 YAML 文件吗?

问题描述

考虑以下文件:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

它利用了 YAML 的合并键特性。

这是一个有效的 YAML 文件吗?规范 ( 1.1 , 1.2 ) 说在映射节点中存在“每个键都是唯一的限制”,但是不清楚合并键本身是否受到唯一性约束,或者是否只有映射键之后已解决的合并必须是唯一的。

PyYAML 解析并合并键,但注释丢失。ruamel 能够保留注释但会引发 a DuplicateKeyError,如果您明确允许重复键,那么它会解析但合并会丢失。

这个输入是有效的 YAML 吗?它应该如何在 Python 中正确解析?

标签: pythonparsingyamlpyyamlruamel.yaml

解决方案


合并键就像任何其他键一样,它们仅在YAML 解析器实现合并键扩展时以特殊定义的方式进行解释(这不是必须的)。在我看来,这是无效的 YAML。

但是,即使合并键非常特殊以至于它不遵循正常的键限制,也有另一个反对这一点的论点。假设您的输入文件如下所示:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0
    VAR2: tater

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1
    VAR2: tuber

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

并且还假设您可以将这个不正确的 YAML 加载到data. 的价值是 data[2]['extra']['VAR2']多少?

由于 YAML 规范明确指出:

特别是,在合成过程中不应引用映射键顺序、注释和标签句柄。

因此,除非您打破另一个明确的限制(密钥排序),否则您无法正确解析它(这就是 PyYAML 所做的。恕我直言,一个错误)。

这意味着当您正确实现 YAML 规范时,您无法决定是先用 a还是用data[2]['extra']更新的值。这就是为什么不允许这样做。VAR2: tuberVAR2: taterruamel.yaml

当然,在合并密钥规范中明确定义了VAR2 您在执行此操作时获得的密钥值:

      <<: [*splat0, *splat1]

推荐阅读