You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用ruamel.yaml将字典Dump为YAML时,使\n、\t等特殊字符正常显示而非保留为转义文本?

解决YAML Dump时特殊字符保留转义的问题

我来帮你搞定这个问题!你遇到的核心问题出在代码里的json.dumps() + json.loads()这一步操作——这会把原本的换行、空格等特殊字符转换成JSON风格的转义序列,而且后续用ruamel.yaml导出时,这些转义字符会被当成普通文本保留,没法还原成你想要的多行格式。

问题根源拆解

ruamel.yaml的RoundTripLoader本来就可以把YAML文件加载成保留原始格式信息的特殊字典对象(比如CommentedMap),但你用json.dumps()把这个对象转成JSON字符串时,所有原生的换行符\n会被转义成\\n;再用json.loads()转回来,字符串里就真的存了\n这两个字符,而不是换行符本身。所以最后dump到YAML时,自然会把这些转义字符原样输出。

修复方案

1. 移除多余的JSON转换步骤

首先删掉这两行完全没必要的代码:

data = json.loads(json.dumps(data))

这一步不仅破坏了ruamel.yaml保留的格式信息,还直接导致了转义问题。

2. 用ruamel.yaml的ScalarString处理多行文本

如果你希望多行字符串直接以换行形式输出到YAML(而不是带转义的字符串),可以用ruamel.yaml提供的LiteralScalarString类来包装你的多行字符串,它会告诉YAML解析器把这个字符串当成字面块输出,保留所有换行和空格。

修改后的完整代码如下:

import ruamel.yaml as yaml
from ruamel.yaml.scalarstring import LiteralScalarString

# 替换成你的原始文件路径
original_file = "your_input.yaml"
# 替换成你要更新的字典
other_dict = {}

with open(original_file) as file:
    # 用RoundTripLoader加载,保留原始结构信息
    data = yaml.load(file, yaml.RoundTripLoader)

# 如果是直接赋值多行字符串,用LiteralScalarString包装
data["description"] = LiteralScalarString("select\n table_name.table_column\n from\n table_info info,\n person\n where id  = person_thing\n")

# 如果是从other_dict更新,记得把里面的多行字符串也包装一下
# 比如:
# if "description" in other_dict:
#     other_dict["description"] = LiteralScalarString(other_dict["description"])
data.update(other_dict)

with open("file_new.yaml", "w") as file:
    yaml.dump(data, file, default_flow_style=False, Dumper=yaml.RoundTripDumper)

最终输出效果

运行这段代码后,生成的YAML文件会是你期望的格式:

name: Ex
info:
  info: info
  info: info
description: |
  select
   table_name.table_column
   from
   table_info info,
   person
   where id  = person_thing

这里的|是YAML的字面块标记,它表示后面的内容会保留所有换行和缩进,完全符合你的需求。如果你不想显示|,也可以尝试FoldedScalarString(它会把连续换行转成空格,适合段落文本),但对于你的示例场景,LiteralScalarString是最匹配的选择。

内容的提问来源于stack exchange,提问作者user14289412

火山引擎 最新活动