流行的数据交换格式,即使代表无序/未使用的元素,也能保留输入顺序?

时间:2012-04-20 07:19:28

标签: python json serialization yaml

我最近构建了一个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:

enter image description here

我可以用我眼前可以识别的方式设置我的数据,例如标题是按惯例排列的第一行。

一旦我将其解析为python对象,修改它,并再次将其转换为YAML / JSON / Python,我当然不再有评论或订购。

我很好奇这是否是一个常见问题,或者这是一个我需要发明的轮子。 似乎可以使用OrderedDict并编写一个序列化器(我从未做过......)。

我目前的解决方案是使用YAML作为只读的原始文本字段 - 它不会尝试将python对象写入YAML以保留样式。

2 个答案:

答案 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不包含普通dictcode个对象,而是包含附加注释的包装版本。

¹使用pip install ruamel.yaml安装。适用于Python 2.6 / 2.7 / 3.3 +
² ordereddict用于映射,以保持排序