如何让PyYAML将Python对象序列化为YAML中的原生JSON块?
解决PyYAML将JSON块转为带转义字符串的问题
我之前处理WebService测试用例序列化的时候,也碰到过一模一样的问题——想把Request的fields dict直接转成YAML里原生的JSON兼容结构,不用转义,也不想事后再修改生成的YAML文本。下面给你两个不用后处理的解决方案:
方法一:自定义PyYAML代表器,指定dict输出为JSON流风格
PyYAML默认会把dict序列化为块风格(缩进的键值对),但我们可以给需要特殊处理的dict注册一个自定义代表器,让它直接输出流风格(JSON的花括号格式),这样就完全兼容Postman等工具的复制粘贴需求。
代码示例:
import yaml from yaml.representer import Representer # 定义一个标记类,用来区分需要按JSON风格输出的dict class JSONCompatibleDict(dict): pass # 自定义代表器:将JSONCompatibleDict序列化为流风格的映射(和JSON格式一致) def represent_json_style_dict(dumper, data): # flow_style=True 强制使用花括号的流风格 return dumper.represent_mapping('tag:yaml.org,2002:map', data, flow_style=True) # 给PyYAML注册这个代表器 yaml.add_representer(JSONCompatibleDict, represent_json_style_dict) # 使用示例 # 假设你的Request.fields是这个dict request_fields = { "endpoint": "/api/webservice", "method": "POST", "headers": {"Content-Type": "application/json"}, "body": {"user_id": 1001, "payload": "test_data"} } # 把fields转换成我们的标记类 json_ready_fields = JSONCompatibleDict(request_fields) # 构造测试用例结构 test_case = { "test_name": "WebService Login Test", "request": json_ready_fields, "expected_response": {"code": 200, "message": "success"} } # 序列化输出 yaml_result = yaml.dump(test_case, default_flow_style=False, sort_keys=False) print(yaml_result)
输出的YAML会是这样的(request部分直接是JSON兼容的结构):
test_name: WebService Login Test request: {endpoint: "/api/webservice", method: "POST", headers: {"Content-Type": "application/json"}, body: {"user_id": 1001, "payload": "test_data"}} expected_response: code: 200 message: success
方法二:用ruamel.yaml简化配置(更省心)
如果你不想写自定义代表器,可以用ruamel.yaml这个增强版的YAML库,它支持更灵活的输出控制,能自动让嵌套的小字典用流风格输出,完全符合你的需求。
首先安装库:
pip install ruamel.yaml
代码示例:
from ruamel.yaml import YAML import sys yaml = YAML() # 设置default_flow_style为None:顶层用块风格,嵌套的小字典自动用流风格(JSON式) yaml.default_flow_style = None # 保持键的原有顺序 yaml.sort_keys = False # 构造测试用例 test_case = { "test_name": "WebService Login Test", "request": { "endpoint": "/api/webservice", "method": "POST", "headers": {"Content-Type": "application/json"}, "body": {"user_id": 1001, "payload": "test_data"} }, "expected_response": {"code": 200, "message": "success"} } # 输出到控制台(也可以写入文件) yaml.dump(test_case, sys.stdout)
输出的YAML和方法一的效果一致,而且不需要额外标记dict,非常省心。
原理说明
你之前用json.dumps转成字符串再序列化,PyYAML会把它当成普通字符串处理,所以会加转义符;用|字面量块的话,它还是字符串类型,需要手动解析。而上面的方法是直接让PyYAML把指定的dict序列化为YAML的映射类型,同时用流风格(花括号)输出,这种格式和JSON完全兼容,所以可以直接复制到Postman等工具里使用,完全不需要后处理。
内容的提问来源于stack exchange,提问作者Kim
相关产品推荐
相关产品推荐

