如何让python -mjson.tool保持属性的顺序?

4

除了这个简单的调用:python -m json.tool {someSourceOfJSON},我对Python知之甚少。

请注意,源文档的顺序是"id"、"z"、"a",但生成的JSON文档呈现的属性是"a"、"id"、"z"。

$ echo '{ "id": "hello", "z": "obj", "a": 1 }' | python -m json.tool
{
    "a": 1,
    "id": "hello",
    "z": "obj"
}

我该如何或者说能否让json.tool保持原始JSON文档属性的顺序?

Python版本是随此MacBookPro自带的。

$ python --version
Python 2.7.15

2
sort_keys=False应该是传递给json.tool的参数,但我不确定如何将其传递给模块。这很奇怪,因为他们添加了--sort-keys标志,旨在实际对键进行排序。你是否碰巧使用旧版本的Python?因为我无法重现这个问题。 - Torxed
问题在于如果 JSON 工具返回一个字典,那么顺序就会被破坏。你的目标是什么? - Jean-François Fabre
2
Python字典自3.7版本开始只保留键的输入顺序。早期版本则不支持此功能。 - BoarGules
1
@BoarGules 这就解释了,我们这里默认运行的是3.7.2版本。 - Torxed
1个回答

6

我不确定是否可以使用 python -m json.tool 实现,但可以使用一行命令解决(我猜这可能是实际的X/Y根问题):

echo '{ "id": "hello", "z": "obj", "a": 1 }' | python -c "import json, sys, collections; print(json.dumps(json.loads(sys.stdin.read(), object_pairs_hook=collections.OrderedDict), indent=4))"

结果:

{
    "id": "hello",
    "z": "obj",
    "a": 1
}

这基本上是以下代码,但没有即时对象和一些可读性妥协,例如单行导入。
import json
import sys
import collections

# Read from stdin / pipe as a str
text = sys.stdin.read()

# Deserialise text to a Python object.
# It's most likely to be a dict, depending on the input
# Use `OrderedDict` type to maintain order of dicts.
my_obj = json.loads(text, object_pairs_hook=collections.OrderedDict)

# Serialise the object back to text
text_indented = json.dumps(my_obj, indent=4)

# Write it out again
print(text_indented)

1
不错。这距离我再也不理解它的工作原理只有一个别名的距离了;)我真的应该学一些Python。 - Bob Kuhar
@BobKuhar 我已经更新了答案,包括为什么这个方法有效的解释。希望它能帮助你入门Python。 - Alastair McCormack
这太棒了。在我的情况下,我想对它们进行排序,但 json.tool 使它们变得随机。我使用了您的方法,并加上了 sort_keys=True - garafajon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接