Ok so I can use an OrderedDict in json.dump
. That is, an OrderedDict can be used as an input to JSON.
But can it be used as an output? If so how? In my case I'd like to load
into an OrderedDict so I can keep the order of the keys in the file.
If not, is there some kind of workaround?
The normally used load command will work if you specify the object_pairs_hook parameter:
In addition to dumping the ordered list of keys alongside the dictionary, another low-tech solution, which has the advantage of being explicit, is to dump the (ordered) list of key-value pairs
ordered_dict.items()
; loading is a simpleOrderedDict(<list of key-value pairs>)
. This handles an ordered dictionary despite the fact that JSON does not have this concept (JSON dictionaries have no order).It is indeed nice to take advantage of the fact that
json
dumps the OrderedDict in the correct order. However, it is in general unnecessarily heavy and not necessarily meaningful to have to read all JSON dictionaries as an OrderedDict (through theobject_pairs_hook
argument), so an explicit conversion of only the dictionaries that must be ordered makes sense too.Some great news! Since version 3.6 the cPython implementation has preserved the insertion order of dictionaries (https://mail.python.org/pipermail/python-dev/2016-September/146327.html). This means that the json library is now order preserving by default. Observe the difference in behaviour between python 3.5 and 3.6. The code:
In py3.5 the resulting order is undefined:
In the cPython implementation of python 3.6:
The really great news is that this has become a language specification as of python 3.7 (as opposed to an implementation detail of cPython 3.6+): https://mail.python.org/pipermail/python-dev/2017-December/151283.html
So the answer to your question now becomes: upgrade to python 3.6! :)
Simple version for Python 2.7+
Or for Python 2.4 to 2.6
Yes, you can. By specifying the
object_pairs_hook
argument to JSONDecoder. In fact, this is the exact example given in the documentation.You can pass this parameter to
json.loads
(if you don't need a Decoder instance for other purposes) like so:Using
json.load
is done in the same way:You could always write out the list of keys in addition to dumping the dict, and then reconstruct the
OrderedDict
by iterating through the list?