我有一个我要解析的YAML文件。
出于多种原因,我想禁止在或锚点中使用点.
,只需在解析时将其替换为_
。
简单地说,我想离开这个:
foo:
bar.baz:
- egg
- spam
到那个:
foo:
bar_baz:
- egg
- spam
我知道这种转换可以在生成的Python字典上执行,但它不适合它:解析器应该抛出错误,或者它应该替换有问题的值。
我已经尝试将Loader
子类化以进行此类转换,但是所有被覆盖的函数都没有任何效果。
答案 0 :(得分:0)
没有简单的机制来替换每个映射键通过的钩子形式的键(无论如何,您可能希望拥有更多的上下文,而不仅仅是拥有键)。 有多种方法可以解决这个问题:
Loader
,它将拥有您自己的Constructor
子类,用于对映射键进行转换。这是IMO的正确解决方案,因为它不会影响其他YAML的加载。然而,这也是一个比较棘手的方法后者可以通过以下方式完成:
import sys
import ruamel.yaml
yaml_str = """\
foo:
bar.baz:
- egg
- spam
"""
def alt_construct_mapping(self, *args, **kw):
"""replace keys with dot"""
m = self.org_construct_mapping(*args, **kw)
for k in m:
if '.' in k:
m[k.replace('.', '_')] = m.pop(k)
return m
# backup up the constructor
ruamel.yaml.constructor.BaseConstructor.org_construct_mapping = \
ruamel.yaml.constructor.BaseConstructor.construct_mapping
# replace the constructor
ruamel.yaml.constructor.BaseConstructor.construct_mapping = alt_construct_mapping
data = ruamel.yaml.safe_load(yaml_str)
ruamel.yaml.round_trip_dump(data, sys.stdout)
# put original constructor back
ruamel.yaml.constructor.BaseConstructor.construct_mapping = \
ruamel.yaml.constructor.BaseConstructor.org_construct_mapping
给出:
foo:
bar_baz:
- egg
- spam
这是使用ruamel.yaml
完成的,这是PyYAML的增强版本,我是作者。对于PyYAML,只要您的YAML没有任何YAML版本1.2结构,将ruamel.yaml
替换为yaml
,将round_trip_load/dump
替换为safe_load/dump