Python用ruamel.yaml为任意嵌套的指定键值添加双引号
ruamel.yaml 如何在dump阶段为指定键的取值强制添加双引号?
需求是:无论嵌套层级多深,只要键名匹配指定列表(比如示例中的grouping),对应取值就用双引号包裹,其余键的取值保持默认无引号格式。
你已经通过预处理数据、将目标键的取值转为DoubleQuotedScalarString实现了需求,下面给出在dump阶段直接实现的方案:
实现思路
ruamel.yaml的序列化依赖代表器(Representer),我们可以重写字典映射的代表逻辑,在处理每个键值对时判断键是否属于目标列表,若是则将其值转为双引号标量字符串后再序列化,同时递归处理嵌套的字典和列表结构。
代码示例
import sys from ruamel.yaml import YAML, Representer from ruamel.yaml.scalarstring import DoubleQuotedScalarString data = { 'simple': 'nonquoted', 'grouping': 'quoted', 'deep': { 'simple': 'nonquoted', 'grouping': 'quoted', }, 'list_example': [ {'grouping': 'in_list'}, {'simple': 'normal'} ] } class CustomRepresenter(Representer): def __init__(self, *args, quote_keys=None, **kwargs): super().__init__(*args, **kwargs) self.quote_keys = quote_keys or set() def represent_mapping(self, tag, mapping, flow_style=None): processed_items = [] for key, value in mapping.items(): if key in self.quote_keys and isinstance(value, str): # 将目标键的字符串值转为双引号格式 quoted_val = DoubleQuotedScalarString(value) processed_items.append((self.represent_data(key), self.represent_data(quoted_val))) else: # 递归处理嵌套结构 if isinstance(value, dict): processed_val = self.represent_mapping(tag, value, flow_style) elif isinstance(value, list): processed_val = self.represent_sequence('tag:yaml.org,2002:seq', value, flow_style) else: processed_val = self.represent_data(value) processed_items.append((self.represent_data(key), processed_val)) return super().represent_mapping(tag, mapping, flow_style) def test(): yaml = YAML() yaml.default_flow_style = False # 绑定自定义代表器,并指定需要双引号的键 yaml.Representer = CustomRepresenter yaml.representer.quote_keys = {'grouping'} yaml.dump(data, sys.stdout) test()
输出结果
simple: nonquoted grouping: "quoted" deep: simple: nonquoted grouping: "quoted" list_example: - grouping: "in_list" - simple: normal
说明
- 该方案无需修改原始数据,所有处理都在序列化阶段完成,适合需要保留原始数据结构的场景。
- 代码中仅处理字符串类型的值,若需要对非字符串值(如数字)也添加双引号,可去掉
isinstance(value, str)的判断。 - 适配你的环境:Python 3.10.13 + ruamel.yaml 0.18.6。
内容的提问来源于stack exchange,提问作者tuck1s
相关产品推荐
相关产品推荐

