Pyyaml 嵌套对象

Pyyaml nested objects

我想用 PyYaml 解释以下 YAML 字符串:

      - !Table
        header:
          - !Column
            - !Paragraph
              text: 'header1'
          - !Column 
            - !Paragraph
              text: 'header2'

我有 Table 和 class 段继承自 yaml.YAMLObject class。但是我不知道如何处理 !Column 标签?此标记应仅被视为命名数组标记。

当我想从 yaml.load() 函数构建对象时,出现以下错误:

yaml.constructor.ConstructorError: could not determine a constructor 
for the tag '!Column'
in "<unicode string>", line 19, column 17:
              - !Column
                ^

使用yaml.YAMLObject有两个问题:

  • 使用默认 yaml.Loader 以外的任何东西都是不透明的,这会迫使您使用不安全的 yaml.load(),除非您现在和将来都可以完全控制输入,否则您不应该这样做.
  • 您不能将它用于由标量或序列组成的节点对象。只能使用映射。

你的!Table!Paragraph是映射节点。但是您的 !Column 是一个序列,您明确需要为此创建一个构造函数:

import sys
from ruamel import yaml

yaml_str = """\
- !Table
  header:
    - !Column
      - !Paragraph
        text: 'header1'
    - !Column
      - !Paragraph
        text: 'header2'

"""

class Table(yaml.YAMLObject):
    yaml_tag = u'!Table'
    pass


class Paragraph(yaml.YAMLObject):
    yaml_tag = u'!Paragraph'
    pass

def column_constructor(loader, node):
    return loader.construct_sequence(node)

yaml.add_constructor('!Column', column_constructor)


data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout, default_flow_style=False)

这会打印:

- !Table
  header:
  - - !Paragraph
      text: header1
  - - !Paragraph
      text: header2

and(因为我用的是ruamel.yaml,也是一个UnsafeLoaderWarning)。

如果你希望输出包含 !Column 那么你应该制作一个 python class Column(list) 并让 column_constructor 返回那个类型,并且另外为 Column 编写一个表示器并将其添加到加载器中。