0

我最近构建了一个 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 以保留样式。

4

2 回答 2

1

通常,字典没有排序,这就是改变顺序的原因......

一种可能的方法可能是在字典上使用排序功能(然后将其转换为OrderedDict... 或者您甚至根本不需要OrderedDict)。但是该顺序为升序/降序,因此可能无济于事...

最终的解决方案可能是查找所有字典并根据需要一一挑选键,然后将它们放到您的OrderedDict

这是一个关于字典排序的好问题......

于 2012-04-20T07:58:20.737 回答
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.

        '

这是第一次往返后的稳定输出。

不是普通的listdict对象,而是code由附有评论的包装版本²组成。

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

于 2014-11-24T11:31:06.327 回答