【问题标题】:Combining YAML Objects via anchors and overriding object values通过锚点和覆盖对象值组合 YAML 对象
【发布时间】:2021-12-11 19:48:00
【问题描述】:

我正在尝试通过在 YAML 中使用锚标记来减少复制相同配置数据(存储在 YAML 文件中)的麻烦。 YAML 示例如下所示:

profiles:
  home: &home
    key1: value1
    object1:
      subKey1: subVal1
      subKey2: subVal2
      complexObject:
        something: value
        someOtherThing: value
  
  work: 
    <<: *home
    object1:
      subKey2: completelyDifferentValue # something like this ?!
      complexObject.something: notValue # or something like this ? 

上述 YAML 的等效 JSON 是

{
    "profiles": {
        "home": {
            "key1": "value1",
            "object1": {
                "subKey1": "subVal1",
                "subKey2": "subVal2",
                "complexObject": {
                    "something": "value",
                    "someOtherThing": "value"
                }
            }
        },
        "work": {
            "key1": "value1",
            "object1": {
                "subKey2": "completelyDifferentValue",
                "complexObject.something": "notValue"
            }
        }
    }
}

而我想要的是:

{
    "profiles": {
        "home": {
            "key1": "value1",
            "object1": {
                "subKey1": "subVal1",
                "subKey2": "subVal2",
                "complexObject": {
                    "something": "value",
                    "someOtherThing": "value"
                }
            }
        },
        "work": {
            "key1": "value1",
            "object1": {
                "subKey1": "subVal1",
                "subKey2": "completelyDifferentValue",
                "complexObject": {
                    "something": "notValue",
                    "someOtherThing": "value"
                }
            }
        }
    }
}

(被移除的附加 subKey1) YAML 配置文件将在 Objects 中包含 Objects,想法是拥有一个父对象,然后复制它并修改一些键(在子对象对象内)

  • 我知道 YAML 规范在这种情况下可能没有直接的帮助,并且希望通过 pyyaml(或其他一些库)在 python 中提供任何解决方法!

【问题讨论】:

    标签: python dictionary yaml pyyaml


    【解决方案1】:

    由于Java的不良影响,人们普遍认为这两种YAML结构是等价的:

    a.b: c
    
    a:
      b:
        c
    

    他们不是。 YAML 中的句点是一个内容字符,就像 a,使第一个 YAML 有一个名为 a.b 的键,暗示嵌套映射。


    现在关于合并:锚点和别名的存在是为了能够序列化任意的、可能是循环的图。递归下降(根据深度合并的需要)需要警惕这样的循环,这就是为什么我假设 &lt;&lt; 被指定不这样做。

    &lt;&lt; 的实际作用是为这个特定的字符序列分配了标签!!merge。然后,YAML 处理器将合并实现为“对于每个具有标签 !!merge 的键的映射,将未知键值对从该键的值中拉到当前映射中”。

    你的问题是,虽然像 PyYAML 这样的库允许你为用户定义的标签注册自定义构造函数,但这些只能为标记的项目生成一个值——然而,!!merge 会影响映射 around em> 标记值,因此其语义不能通过自定义构造函数轻松复制和扩展。

    但是,您可以简单地覆盖 PyYAML 的合并实现。为此,根据您的需要从SafeConstructorFullConstructorUnsafeConstructor 继承,重新实现flatten_mapping,然后定义一个使用您的构造函数的加载程序(see here)。理论上,除了深度合并之外,您还可以在这里实现周期嵌套映射,但我不建议这样做。然后,这些只会在您进行合并的地方起作用,而不是在其他地方起作用,这是违反直觉的。

    【讨论】:

      猜你喜欢
      • 2021-12-30
      • 1970-01-01
      • 2021-09-14
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 2019-10-04
      相关资源
      最近更新 更多