json.dumps messes up order

Question:

I’m working with the json module creating a json file containing entries of the like

json.dumps({"fields": { "name": "%s", "city": "%s", "status": "%s", "country": "%s" }})

However, in the json-file created the fields are in the wrong order

{"fields": {"status": "%s", "city": "%s", "name": "%s", "country": "%s"}}

which is a problem because the substitions for the %s-strings are now incorrect.

How can I force the dumps function to keep the given order?

Asked By: TheWaveLad

||

Answers:

This is a dictionary, and dictionaries don’t keep order.
You can use OrderedDict instead.

You could also add the sort_keys=False parameter:

json.dumps(values, sort_keys=False)
Answered By: ShacharSh

Like the other answers correctly state, before Python 3.6, dictionaries are unordered.

That said, JSON is also supposed to have unordered mappings, so in principle it does not make much sense to store ordered dictionaries in JSON. Concretely, this means that upon reading a JSON object, the order of the returned keys can be arbitrary.

A good way of preserving the order of a mapping (like a Python OrderedDict) in JSON is therefore to output an array of (key, value) pairs that you convert back to an ordered mapping upon reading:

>>> from collections import OrderedDict
>>> import json
>>> d = OrderedDict([(1, 10), (2, 20)])                                         
>>> print d[2]
20
>>> json_format = json.dumps(d.items())                   
>>> print json_format  # Order maintained
[[1, 10], [2, 20]]
>>> OrderedDict(json.loads(json_format))  # Reading from JSON: works!
OrderedDict([(1, 10), (2, 20)])
>>> _[2]  # This works!
20

(Note the way the ordered dictionary is constructed from a list of (key, value) pairs: OrderedDict({1: 10, 2: 20}) would not work: its keys are not necessarily ordered as in the dictionary literal, since the literal creates a Python dictionary whose keys are unordered.)

PS: Starting with Python 3.1, the json modules offers a hook for automatically converting a list of pairs (like above) to something else like an OrderedDict.

Answered By: Eric O Lebigot

You cannot create an OrderedDict from a dict because order has already changed the moment you create a dictionary.So best way is to use tuples to create a OrderedDict

from collections import OrderedDict
import json

a = (("name","foo"),("city","bar"),("status","baz"),("country","my"))

b = OrderedDict(a)

c = {"fileds": b}

print json.dumps(c)
Output:
{"fileds": {"name": "foo", "city": "bar", "status": "baz", "country": "my"}}
Answered By: Ajay

You can choose OrderedDict to be used instead of an ordinary dict when creating a json object to remember the order of insertions:

>>> from collections import OrderedDict
>>> a = '{"fields": { "name": "%s", "city": "%s", "status": "%s", "country": "%s" }}'
>>> b = json.loads(a, object_pairs_hook=OrderedDict)
>>> json.dumps(b)
'{"fields": {"name": "%s", "city": "%s", "status": "%s", "country": "%s"}}'
Answered By: Antony Hatchkins

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}'
Answered By: Lane Lee
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.