将对象转储到不带引号的 yaml 中

Dump object into yaml without quotes

我有一些我想变成 yaml 的对象,唯一的问题是我需要能够将不带引号的“!任何东西”放入其中。

当我尝试使用 pyyaml 时,我的 yaml 文件中出现了“!anything”。

我已经尝试使用 ruamel.yaml PreservedScalarString 和 LiteralScalarString。它有点管用,但不是我需要的工作方式。问题是我最终得到了如下所示的 yaml:

10.1.1.16:
            text: '1470814.27'
            confidence: |-
              !anything

但我不需要这个 |- 符号。

我的目标是像这样获得 yaml:

10.1.1.16:
            text: '1470814.27'
            confidence: !anything

有什么办法可以实现吗?

要转储自定义标签,您需要定义一个类型并为该类型注册一个代表。以下是对标量的处理方法:

import yaml

class MyTag:
  def __init__(self, content):
    self.content = content

  def __repr__(self):
    return self.content

  def __str__(self):
    return self.content

def mytag_dumper(dumper, data):
  return dumper.represent_scalar("!anything", data.content)

yaml.add_representer(MyTag, mytag_dumper)

print(yaml.dump({"10.1.1.16": {
    "text": "1470814.27",
    "confidence": MyTag("")}}))

这会发出

10.1.1.16:
  confidence: !anything ''
  text: '1470814.27'

注意标签后面的'',这是被标记的标量(不,你不能去掉它)。您也可以标记集合,但您需要相应地使用 represent_sequencerepresent_mapping

与@flix 评论相反,在 YAML 中,您不需要在标签后加上单引号或双引号(或块标量)。您可以尝试 Oren Ben-Kiki 的 reference parser(以编程方式从 YAML 规范派生)来确认您的预期输出是有效的 YAML。

空内容通常在 Python 中加载为 None(由过时的 PyYAML 和 ruamel.yaml 加载)。标记为空的内容当然可以只表示特定实例的存在,而不表示任何值。

ruamel.yaml 可以很好地 round-trip 你的预期输出:

import sys
from ruamel.yaml import YAML

yaml_str = """\
10.1.1.16:
  text: '1470814.27'
  confidence: !anything
"""

yaml = YAML()
data = yaml.load(yaml_str)

yaml.dump(data, sys.stdout)

给出:

10.1.1.16:
  text: '1470814.27'
  confidence: !anything

您可以生成一个只转储没有值的标签的对象(就像解析器那样),但是如果您不想深入了解细节,您可以只加载标记的对象并添加它到您的数据结构:

import sys
import ruamel.yaml


yaml = ruamel.yaml.YAML()


def tagged_empty_scalar(tag):
   return yaml.load('!' + tag)

data = {'10.1.1.16': dict(text='1470814.27', confidence=tagged_empty_scalar('anything'))}

yaml.dump(data, sys.stdout)

您可以在 PyYAML 中获得完全相同的结果,但不带引号,但更复杂。