是否有共享列表或地图的一部分的YAML语法?
所以,我知道我可以做这样的事情:
sitelist: &sites - www.foo.com - www.bar.com anotherlist: *sites
并且有网站anotherlist
和anotherlist
都包含www.foo.com
和anotherlist
。 但是,我真正想要的是anotherlist
也包含www.baz.com
,而不必重复www.foo.com
和www.baz.com
。
这样做给了我在YAML分析器中的语法错误:
sitelist: &sites - www.foo.com - www.bar.com anotherlist: *sites - www.baz.com
只要使用锚和别名,似乎不可能做我想要的,而不增加另一层子结构,如:
sitelist: &sites - www.foo.com - www.bar.com anotherlist: - *sites - www.baz.com
这意味着这个YAML文件的使用者必须意识到这一点。
有没有一种纯粹的YAML做这样的事情? 或者我将不得不使用一些YAML后处理,例如实现某些子结构的variablesreplace或自动提升? 我已经在做这种后处理来处理其他一些用例,所以我并不完全反对。 但是我的YAML文件将被人类编写,而不是机器生成的,所以我想在标准YAML语法的基础上尽量减less我的用户需要记住的规则的数量。
我也想用地图做类似的事情:
namedsites: &sites Foo: www.foo.com Bar: www.bar.com moresites: *sites Baz: www.baz.com
我已经通过YAML规范search,找不到任何东西,所以我怀疑答案只是“不,你不能这样做”。 但是,如果有人有任何想法,将是伟大的。
编辑:由于没有答案,我假设没有人发现任何我没有在YAML规范,这不能在YAML层完成。 所以我打开这个问题来想想后期处理YAML来帮助解决这个问题,以防将来有人发现这个问题。
合并密钥types可能是你想要的。 它使用一个特殊的<<
映射关键字来表示合并,允许一个映射的别名(或者这样的别名序列)被用作一个初始化器来合并成一个映射。 此外,您仍然可以显式重写值,或者添加更多不存在于合并列表中的值。
重要的是要注意,它与映射一起工作,而不是序列作为第一个例子。 这是有道理的,当你考虑它,你的例子看起来可能不需要按顺序。 简单地改变你的序列值到映射键应该做的伎俩,如下面(未经testing)的例子:
sitelist: &sites ? www.foo.com # "www.foo.com" is the key, the value is null ? www.bar.com anotherlist: << : *sites # merge *sites into this mapping ? www.baz.com # add extra stuff
有些事情要注意。 首先,由于<<
是一个关键,因此每个节点只能指定一次。 其次,当使用序列作为值时,顺序是显着的。 这里没有关系,因为没有关联的值,但值得注意。
(回答我自己的问题,以防万一我使用的解决scheme对于将来search这个的人有用)
由于没有使用纯YAML的方法,所以我将把它作为一个位于YAMLparsing器和实际使用configuration文件的代码之间的“语法转换”来实现。 因此,我的核心应用程序不必担心任何人性化的冗余避免措施,并可以直接对结果进行操作。
我要使用的结构如下所示:
foo: MERGE: - - a - b - c - - 1 - 2 - 3
这将转化为相当于:
foo: - a - b - c - 1 - 2 - 3
或者,用地图:
foo: MERGE: - fork: a spoon: b knife: c - cup: 1 mug: 2 glass: 3
将被转换为:
foo: fork: a spoon: b knife: c cup: 1 mug: 2 glass: 3
更正式地说,在调用YAMLparsing器从configuration文件中获取本地对象之后,在将对象传递给应用程序的其余部分之后,我的应用程序将遍历对象图,查找包含单个键MERGE
映射。 与MERGE
相关联的值必须是列表的列表或地图列表; 任何其他子结构是一个错误。
在list-of-lists的情况下,包含MERGE
的整个地图将被replace为按照它们出现的顺序连接在一起的子列表。
在地图列表的情况下,包含MERGE
的整个地图将由包含子地图中的所有键/值对的单个地图replace。 在键中有重叠的地方,将使用最后在MERGE
列表中出现的子地图的值。
上面的例子没有用,因为你可以直接写出你想要的结构。 这更可能performance为:
foo: MERGE: - *salt - *pepper
允许您创build一个列表或地图,其中包含节点salt
和pepper
在其他地方使用的所有内容。
(我一直给这个foo:
outer map来表明MERGE
必须是它映射中的唯一键,这意味着MERGE
不能出现在顶级名字上,除非没有其他的顶级名字)
要搭载Kittemon的答案,请注意,您可以使用替代语法创build具有空值的映射
foo: << : myanchor bar: baz:
而不是build议的语法
foo: << : myanchor ? bar ? baz
像Kittemon的build议一样,这将允许您在映射中使用对锚点的引用并避免序列问题。 发现Symfony Yaml组件v2.4.4没有logging下来,我发现自己需要这样做? bar
? bar
语法。
为了澄清这里的两个答案,YAML不直接支持列表(但它支持字典,请参阅kittemon的答案)。
正如前面的答案所指出的那样,在YAML中没有内置的扩展列表支持。 我提供了另一种自己实现的方法。 考虑一下:
defaults: &defaults sites: - www.foo.com - www.bar.com setup1: <<: *defaults sites+: - www.baz.com
这将被处理成:
defaults: sites: - www.foo.com - www.bar.com setup1: sites: - www.foo.com - www.bar.com - www.baz.com
这个想法是把一个以'+'结尾的密钥的内容合并到没有'+'的对应密钥。 我用Python实现了这个,并在这里发布。
请享用!