问题很简单,但要正确说出来有点棘手。
基本上,我有一本包含以下数据的字典:
x = { foo: [1, '\n', 'bar'] }
当我使用带有yaml.safe_dump(x, default_flow_style=False)
的pyyaml转换为yaml时,我希望输出为:
foo:
- 1
- '\n'
- bar
但是,我得到了像
这样的东西foo:
- 1
- '
'
- bar
实际上正在解释换行符,而不是作为'\ n'字符串传递。
我一直在查看pyyaml文档,但没有看到正确的解法让这个东西正确解析。
之前有没有人处理过同样的问题?你是怎么解决的?
提供更多背景信息。
我有一个json,我想转换为yaml。
具有以下内容的文件:
{
"content": {
"Fn::Join": ["\n", [{ "Ref": "parentStackName" }, ""]]
}
}
最终结果应为:
content:
Fn::Join:
- "\n"
- - Ref: parentStackId
- ''
注意"\n"
只是一个字符串,而不是实际字符。
我正在使用的程序是:
当我创建dict时,您可以看到“\ n”作为字符串的一部分。当pyyaml将其转移到yaml中时,事情就会出错。
答案 0 :(得分:2)
要获得所需的输出,您可以使用ruamel.yaml的往返功能,并更新YAML的JSON子集用于阻止样式的流式:
import sys
import ruamel.yaml
from ruamel.yaml.comments import CommentedMap, CommentedSeq
# because this is a string and not read from file, you need to escape
# the backslash in \n
json_str = """\
{
"content": {
"Fn::Join": ["\\n", [{ "Ref": "parentStackName" }, ""]]
}
}
"""
def block_style(base):
"""set all mapping and sequneces to block-style"""
if isinstance(base, CommentedMap):
for k in base:
block_style(base[k])
base.fa.set_block_style()
if isinstance(base, list):
for item in base:
block_style(item)
base.fa.set_block_style()
return base
data = ruamel.yaml.round_trip_load(json_str)
block_style(data)
ruamel.yaml.round_trip_dump(data, sys.stdout)
给出:
content:
Fn::Join:
- "\n"
- - Ref: parentStackName
- ''
ruamel.yaml
是PyYAML的更新版本(免责声明:我是作者)。它支持YAML 1.2规范(从2009年开始),它使YAML更符合JSON的完整超集,并允许您使用ruamel.yaml解析器读取您的JSON(PyYAML仅支持大部分YAML 1.1规范)。
在“往返模式”中,ruamel.yaml
的增强功能包括保持流量。单个基础上的复合节点(映射和序列)的块样式(以及各种引用样式,注释和标记名称)。 block_style()
的作用是递归地将“flow-attribute”.fa
更改为所有复合节点的块样式。
答案 1 :(得分:-1)
当字符串包含特殊字符时,请使用原始字符串:
$ cat /tmp/tmp.py
import yaml
foo = 'foo'
x = { foo: [1, r'\n', 'bar'] }
y = yaml.safe_dump(x, default_flow_style=False)
print(y)
$ python3 /tmp/tmp.py
foo:
- 1
- \n
- bar