我最近构建了一个django JSON字段,YAML字段,Python字段,以探索通过CMS存储/编辑任意复杂的数据层次结构的方法。
JSON,YAML和Python都可以直观地进行人工格式化,但只要我将文本强制转换为python并返回,它就会创建一个没有排序的新对象。
是否存在透明保留输入顺序的便携式数据方案,即使数据实际上并未按顺序重建原始输入,但“人类”决定构建它?
以python / json为例:
[{
'title': 'First Data Entry!', # intuitive to have certain elements at top
'is_active': True,
'data': 'data here'
'a_list': [1, 2, 3],
},
{
'title': 'Some Data Entry Here!',
'is_active': False,
'data': 'data here'
'a_list': [1, 2, 3],
}]
或YAML:
我可以用我眼前可以识别的方式设置我的数据,例如标题是按惯例排列的第一行。
一旦我将其解析为python对象,修改它,并再次将其转换为YAML / JSON / Python,我当然不再有评论或订购。
我很好奇这是否是一个常见问题,或者这是一个我需要发明的轮子。
似乎可以使用OrderedDict
并编写一个序列化器(我从未做过......)。
我目前的解决方案是使用YAML作为只读的原始文本字段 - 它不会尝试将python对象写入YAML以保留样式。
答案 0 :(得分:1)
通常情况下,字典没有排序,这也是订单变更的原因......
一种可能的方法可能是在字典上使用排序函数(然后将其转换为OrderedDict
...或者甚至根本不需要OrderedDict
。但是这个命令是上升/下降,所以它可能没有帮助......
最终解决方案可能是按照您的意愿逐个删除所有词典并逐个选择键,并将它们放到OrderedDict
Here is a good SO question关于字典排序......
答案 1 :(得分:1)
在python折叠样式(>
)中,不会保留标量,也不会保留标记。
如果您可以放弃折叠样式,可以使用python包¹ruamel.yaml,它是PyYAML的衍生物,支持往返保留注释和往返保留映射键的顺序强>:
from __future__ import print_function
import ruamel.yaml
inp = """\
features:
show: true
items:
- widget: full_width.html # full width 1
title: Some Title
description: >
Foobar.
vimeo_id: 20913
zoom_image: some_url.png
- widget: 3x_container.html
items:
- widget: 3x.html
title: Some Widget Title
image: 'foobar.png'
description: >
Some Description.
- widget: 3x.html
title: Some new title here
image: ajax_uploads/png1_2.png
description: >
Some Description.
"""
code = ruamel.yaml.load(inp, ruamel.yaml.RoundTripLoader)
res = ruamel.yaml.dump(code, Dumper= ruamel.yaml.RoundTripDumper)
print(res, end='')
结果:
features:
show: true
items:
- widget: full_width.html # full width 1
title: Some Title
description: 'Foobar.
'
vimeo_id: 20913
zoom_image: some_url.png
- widget: 3x_container.html
items:
- widget: 3x.html
title: Some Widget Title
image: foobar.png
description: 'Some Description.
'
- widget: 3x.html
title: Some new title here
image: ajax_uploads/png1_2.png
description: 'Some Description.
'
第一次往返后的稳定输出。
list
不包含普通dict
和code
个对象,而是包含附加注释的包装版本。
¹使用pip install ruamel.yaml
安装。适用于Python 2.6 / 2.7 / 3.3 +
子>
² ordereddict
用于映射,以保持排序