如何在dump yaml.MappingNode/ScalarNode时保留标签?
问题描述
已有如下Python代码构建的YAML Node对象:
from yaml import ScalarNode, MappingNode my_obj = { 'test': ScalarNode(tag='!my_tag1', value='test_value'), 'a': MappingNode(tag='!my_tag2', value=[ (ScalarNode(tag='tag:yaml.org,2002:str', value='b'), ScalarNode(tag='tag:yaml.org,2002:int', value='1')), (ScalarNode(tag='tag:yaml.org,2002:str', value='c'), ScalarNode(tag='tag:yaml.org,2002:int', value='1')) ]) }
期望生成的YAML输出为:
test: !my_tag1 test_value a: !my_tag2 b: 1 c: 1
但使用yaml.safe_dump(my_obj)时触发错误:
RepresenterError: ('cannot represent an object', MappingNode(tag='!my_tag2', value=[(ScalarNode(tag='tag:yaml.org,2002:str', value='b'), ScalarNode(tag='tag:yaml.org,2002:int', value='1')), (ScalarNode(tag='tag:yaml.org,2002:str', value='c'), ScalarNode(tag='tag:yaml.org,2002:int', value='1'))]))
需要定义通用的Representer,实现dump通用YAML Node时保留标签和值。
解决方案
要实现需求,需为ScalarNode和MappingNode分别定义自定义Representer,注册到PyYAML的Dumper中,让它能正确处理这些Node类型:
- 定义ScalarNode的Representer:直接利用PyYAML内置的标量处理逻辑,保留标签和值。
- 定义MappingNode的Representer:将Node中的键值对转换为Python字典结构,再应用对应标签进行序列化。
完整代码示例:
import yaml from yaml import ScalarNode, MappingNode, SafeDumper # 为ScalarNode定义Representer def represent_scalar_node(dumper, node): return dumper.represent_scalar(node.tag, node.value) # 为MappingNode定义Representer def represent_mapping_node(dumper, node): # 将MappingNode的value转换为Python字典 mapping = dict(node.value) return dumper.represent_mapping(node.tag, mapping) # 注册自定义Representer到SafeDumper SafeDumper.add_representer(ScalarNode, represent_scalar_node) SafeDumper.add_representer(MappingNode, represent_mapping_node) # 序列化对象 result = yaml.dump(my_obj, Dumper=SafeDumper, default_flow_style=False) print(result)
代码说明
represent_scalar_node:直接调用Dumper的represent_scalar方法,传入Node的标签和值,确保自定义标签被保留。represent_mapping_node:先把MappingNode的value(键值对列表)转为Python字典,再调用represent_mapping方法并传入自定义标签,既能保留标签,又能正确序列化映射结构。- 使用
default_flow_style=False确保输出为块级格式,和期望的YAML结构一致。
运行上述代码后,即可得到符合要求的YAML输出。
内容的提问来源于stack exchange,提问作者Giorgio Di Rocco
相关产品推荐
相关产品推荐

