使用“json.dumps”时 JSON 对象中的项目顺序混乱吗?

2025-01-16 08:38:00
admin
原创
86
摘要:问题描述:我用它json.dumps来转换成 jsoncountries.append({"id":row.id,"name":row.name,"timezone":row.timezone}) print json.dumps(countries...

问题描述:

我用它json.dumps来转换成 json

countries.append({"id":row.id,"name":row.name,"timezone":row.timezone})
print json.dumps(countries)

我得到的结果是:

[
   {"timezone": 4, "id": 1, "name": "Mauritius"}, 
   {"timezone": 2, "id": 2, "name": "France"}, 
   {"timezone": 1, "id": 3, "name": "England"}, 
   {"timezone": -4, "id": 4, "name": "USA"}
]

我希望按以下顺序排列键:id、name、timezone - 但是我得到的却是 timezone、id、name。

我该如何修复这个问题?


解决方案 1:

Python dict(Python 3.7 之前)和 JSON 对象都是无序集合。你可以传递sort_keys参数,对键进行排序:

>>> import json
>>> json.dumps({'a': 1, 'b': 2})
'{"b": 2, "a": 1}'
>>> json.dumps({'a': 1, 'b': 2}, sort_keys=True)
'{"a": 1, "b": 2}'

如果您需要特定的顺序;您可以使用collections.OrderedDict

>>> from collections import OrderedDict
>>> json.dumps(OrderedDict([("a", 1), ("b", 2)]))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict([("b", 2), ("a", 1)]))
'{"b": 2, "a": 1}'

从 Python 3.6 开始,关键字参数顺序被保留,并且可以使用更好的语法重写上述内容:

>>> json.dumps(OrderedDict(a=1, b=2))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict(b=2, a=1))
'{"b": 2, "a": 1}'

参见PEP 468 – 保留关键字参数顺序。

如果您的输入是 JSON 格式,那么为了保留顺序(获取OrderedDict),您可以传递object_pair_hook, 正如@Fred Yankowski 所建议的那样:

>>> json.loads('{"a": 1, "b": 2}', object_pairs_hook=OrderedDict)
OrderedDict([('a', 1), ('b', 2)])
>>> json.loads('{"b": 2, "a": 1}', object_pairs_hook=OrderedDict)
OrderedDict([('b', 2), ('a', 1)])

解决方案 2:

正如其他人提到的,底层字典是无序的。但是 Python 中有 OrderedDict 对象。(它们是在最近的 Python 中内置的,或者您可以使用这个:http ://code.activestate.com/recipes/576693/ )。

我相信较新的 pythons json 实现可以正确处理内置的 OrderedDicts,但我不确定(并且我无法轻松进行测试)。

旧的 pythons simplejson 实现不能很好地处理 OrderedDict 对象...并且在输出它们之前将它们转换为常规字典...但你可以通过执行以下操作来克服这个问题:

class OrderedJsonEncoder( simplejson.JSONEncoder ):
   def encode(self,o):
      if isinstance(o,OrderedDict.OrderedDict):
         return "{" + ",".join( [ self.encode(k)+":"+self.encode(v) for (k,v) in o.iteritems() ] ) + "}"
      else:
         return simplejson.JSONEncoder.encode(self, o)

现在使用这个我们得到:

>>> import OrderedDict
>>> unordered={"id":123,"name":"a_name","timezone":"tz"}
>>> ordered = OrderedDict.OrderedDict( [("id",123), ("name","a_name"), ("timezone","tz")] )
>>> e = OrderedJsonEncoder()
>>> print e.encode( unordered )
{"timezone": "tz", "id": 123, "name": "a_name"}
>>> print e.encode( ordered )
{"id":123,"name":"a_name","timezone":"tz"}

这几乎是所期望的。

另一种选择是专门使用编码器来直接使用你的行类,这样你就不需要任何中间字典或 UnorderedDict。

解决方案 3:

嘿,我知道这个答案已经太晚了,但请添加 sort_keys 并为其分配 false,如下所示:

json.dumps({'****': ***},sort_keys=False)

这对我有用

解决方案 4:

字典的顺序与其定义顺序没有任何关系。所有字典都是如此,而不仅仅是那些转换成 JSON 的字典。

>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}

事实上,这本字典在达到以下程度之前就被“颠倒”了json.dumps

>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}

解决方案 5:

json.dump() 将保留字典的顺序。在文本编辑器中打开该文件,你会看到。无论你是否向其发送 OrderedDict,它都会保留顺序。

但是 json.load() 将丢失已保存对象的顺序,除非您告诉它加载到 OrderedDict() 中,这是使用 object_pairs_hook 参数完成的,正如 JFSebastian 上面指示的那样。

否则它会失去顺序,因为在通常操作下,它会将保存的字典对象加载到常规字典中,而常规字典不会保留给定项目的顺序。

解决方案 6:

如果您使用的是 Python 3.7+,它确实会保留顺序。

在 Python 3.7 之前,dict 不能保证是有序的,因此除非特别请求 collections.OrderedDict,否则输入和输出通常是杂乱的。从 Python 3.7 开始,常规 dict 变为保序的,因此不再需要为 JSON 生成和解析指定 collections.OrderedDict。

https://docs.python.org/3/library/json.html#json.dump

解决方案 7:

根据迈克尔·安德森的回答,但当你传入一个数组时也可以工作

class OrderedJsonEncoder(simplejson.JSONEncoder):
    def encode(self, o, first=True):
        if type(o) == list and first:
            return '[' + ",".join([self.encode(val, first=False) for val in o]) + ']'
        if type(o) == OrderedDict:
            return "{" + ",".join(
                [self.encode(k, first=False) + ":" + self.encode(v) for (k, v) in o.iteritems()]
            ) + "}"
        else:
            return simplejson.JSONEncoder.encode(self, o)

解决方案 8:

Python 3.6.1:

Python 3.6.1 (default, Oct 10 2020, 20:16:48)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import json
>>> json.dumps({'b': 1, 'a': 2})
'{"b": 1, "a": 2}'

Python 2.7.5:

Python 2.7.5 (default, Nov 20 2015, 02:00:19) 
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.

>>> import json
>>> json.dumps({'b': 1, 'a': 2})
'{"a": 2, "b": 1}'
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用