pyyaml解析带有标签的数据

时间:2018-12-08 16:21:53

标签: yaml pyyaml

我有yaml数据,例如下面的输入,我需要将输出作为键值对

输入

a="""
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
code:
- '716'
- '718'
id:
- 488
- 499
"""

需要输入

{'code': ['716', '718'], 'id': [488, 499]}

默认构造函数给我一个错误。我尝试添加新的构造函数,现在它没有给我错误,但是我无法获取键值对。 仅供参考,如果我从Yaml中删除了!ruby/hash:ActiveSupport::HashWithIndifferentAccess行,那么它将为我提供所需的输出。

def new_constructor(loader, tag_suffix, node):

     if type(node.value)=='list':
         val=''.join(node.value)
     else:
         val=node.value
     val=node.value
     ret_val="""
     {0}
     """.format(val)
     return ret_val

yaml.add_multi_constructor('', new_constructor)
yaml.load(a)

output

"\n     [(ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'code'), SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'716'), ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'718')])), (ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'id'), SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'488'), ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'499')]))]\n     "

请提出建议。

2 个答案:

答案 0 :(得分:1)

这不是使用PyYAML的解决方案,但我建议改为使用ruamel.yaml。如果没有其他原因,它比PyYAML更加积极地维护。概述中的报价

  

许多针对PyYAML的错误,但从未得到解决,这些错误已在ruamel.yaml中修复

要加载该字符串,您可以

import ruamel.yaml
parser = ruamel.yaml.YAML()

obj = parser.load(a)  # as defined above.

答案 1 :(得分:0)

我强烈建议您遵循@Andrew F的回答,但如果您 想知道为什么您的代码没有得到正确的结果,这是因为 您没有正确处理标签中标签下的节点 处理。

尽管节点的值是一个列表(包含键值对的元组), 您应该测试节点本身的类型(使用isinstance) 然后将其移交给“常规”映射处理例程 标签在映射上:

import yaml
from yaml.loader import SafeLoader

a = """\
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
code:
- '716'
- '718'
id:
- 488
- 499
"""

def new_constructor(loader, tag_suffix, node):
    if isinstance(node, yaml.nodes.MappingNode):
        return loader.construct_mapping(node, deep=True)
    raise NotImplementedError

yaml.add_multi_constructor('', new_constructor, Loader=SafeLoader)


data = yaml.load(a, Loader=SafeLoader)
print(data)

给出:

{'code': ['716', '718'], 'id': [488, 499]}

您不应该使用PyYAML的yaml.load(),因为它被记录为潜在的不安全因素 最重要的是没有必要。只需将新的构造函数添加到SafeLoader