在python中从JSON创建可逆YAML

时间:2019-05-27 09:11:32

标签: python json yaml

在尝试使用本地yaml库从python中的JSON创建YAML时,我能够将JSON转换为YAML。但是,在收到的YAML中,JSON的所有方括号都展开了,而我想保留从JSON到转换后的YAML的几个方括号(列表)。如何请求此库调用,以不将列表从JSON展开到YAML中,而是将其保留为列表?

以下是我的问题的快照:

import yaml
import json

original_json = {'a': {'next': ['b'], 'prev': []},
 'b': {'next': ['c'], 'prev': ['a']},
 'c': {'next': ['d', 'e'], 'prev': ['b']},
 'd': {'next': [], 'prev': ['c']},
 'e': {'next': ['f'], 'prev': ['c']},
 'f': {'next': [], 'prev': ['e']}}

obtained_yaml = yaml.dump(yaml.load(json.dumps(original_json)), default_flow_style=False)

# obtained_yaml looks like
#
# a:
#   next:
#   - b
#   prev: []
# b:
#   next:
#   - c
#   prev:
#   - a
# c:
#   next:
#   - d
#   - e
#   prev:
#   - b
# d:
#   next: []
#   prev:
#   - c
# e:
#   next:
#   - f
#   prev:
#   - c
# f:
#   next: []
#   prev:
#   - e

# expected yaml should look like
#
# a:
#   next:
#   - ["b"]
#   prev: []
# b:
#   next:
#   - ["c"]
#   prev:
#   - ["a"]
# c:
#   next:
#   - ["d"]
#   - ["e"]
#   prev:
#   - ["b"]
# d:
#   next: []
#   prev:
#   - ["c"]
# e:
#   next:
#   - ["f"]
#   prev:
#   - ["c"]
# f:
#   next: []
#   prev:
#   - ["e"]

我尝试了几种方法来解决这个问题,但是所有这些都无法像预期的json那样工作。需要如何完成的建议。

2 个答案:

答案 0 :(得分:1)

Yaml语法定义了一个不同的列表结构,其中列表的成员是在同一缩进级别以using BaseClass::x; using BaseClass::y; using BaseClass::z; (破折号和空格)开头的行。如果您想保留方括号,则需要将列表强制转换为--但是您将失去将YAML反向转换为JSON的功能。

在此示例中,即使将str放入["a"],您也可以看到-YAML将其转换为双缩进列表:

[["a"]]

答案 1 :(得分:0)

只有YAML 1.2是JSON的超集,但不是YAML 1.1,尽管YAML 1.2是在JSON中发布的 2009年,很遗憾,此后一直没有更新PyYAML。你的例子 是与YAML 1.1兼容的JSON子集,但总的来说这不是一个好主意 尝试为此使用PyYAML。

还有其他适用于Python的本机库,另一个是 ruamel.yaml(免责声明:我是该软件包的作者), 实现YAML 1.2,并提供对块与流的完全控制 个人收藏的样式转储。当然你还有 常规YAML限制,即您不能使用块样式 流样式集合中的集合)。

PyYAML和ruamel.yaml在非往返模式下,仅允许您以流样式拥有所有块或所有流,或所有具有叶节点的块。但是默认的往返模式允许使用集合上的.fa属性进行更精细的控制:

import sys
import json
import ruamel.yaml


original_json = {'a': {'next': ['b'], 'prev': []},
 'b': {'next': ['c'], 'prev': ['a']},
 'c': {'next': ['d', 'e'], 'prev': ['b']},
 'd': {'next': [], 'prev': ['c']},
 'e': {'next': ['f'], 'prev': ['c']},
 'f': {'next': [], 'prev': ['e']}}

json_string = json.dumps(original_json)

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
# yaml.preserve_quotes = True
data = yaml.load(json_string)

# the following sets flow-style for the root level mapping only
data.fa.set_block_style()
yaml.dump(data, sys.stdout)

给出:

a: {next: [b], prev: []}
b: {next: [c], prev: [a]}
c: {next: [d, e], prev: [b]}
d: {next: [], prev: [c]}
e: {next: [f], prev: [c]}
f: {next: [], prev: [e]}

您当然可以递归地遍历数据结构,并根据所需的任何条件调用.fa.set_block_style()