80

I've a problem with JSON in python.

In fact, if I try to execute this code, python gives me a sorted JSON string!

For example:

values = {
  'profile': 'testprofile',
  'format': 'RSA_RC4_Sealed',
  'enc_key': base64.b64encode(chiave_da_inviare),
  'request': base64.b64encode(data)
}

values_json = json.dumps(values, sort_keys = False, separators = (',', ':'))

And this is the output:

{
  "profile": "testprofile",
  "enc_key": "GBWo[...]NV6w==",
  "request": "TFl[...]uYw==",
  "format": "RSA_RC4_Sealed"
}

As you can see, I tried to use "sort_keys=False" but nothing changed.

How can I stop Python sorting my JSON strings?

Mickael Lherminez
  • 679
  • 1
  • 10
  • 29
elledienne
  • 1,135
  • 1
  • 11
  • 18
  • 2
    sort_keys is False by default. https://docs.python.org/3/library/json.html Which python did you use? – Joe C Nov 04 '18 at 05:03
  • As others have noticed, this example output is also un-sorted, just differently than the input example. One of the "features"of hash maps (what Python calls a dict type) is that key order doesn't matter. Output ordering is considered cosmetic. Code logic relying on order is often considered pathological. – MarkHu Mar 31 '20 at 17:37
  • Almost duplicate of [python - Can I get JSON to load into an OrderedDict? - Stack Overflow](https://stackoverflow.com/questions/6921699/can-i-get-json-to-load-into-an-ordereddict) – user202729 Nov 04 '20 at 14:01

6 Answers6

109

Try OrderedDict from the standard library collections:

>>> import json
>>> from collections import OrderedDict
>>> values = OrderedDict([('profile','testprofile'), 
                          ('format', 'RSA_RC4_Sealed'), 
                          ('enc_key', '...'), 
                          ('request', '...')])
>>> json.dumps(values, sort_keys=False)
'{"profile": "testprofile", "format": "RSA_RC4_Sealed", "enc_key": "...", "request": "..."}'

Unfortunately this feature is New in version 2.7 for collections

Tautvydas
  • 2,027
  • 3
  • 25
  • 38
MrGray
  • 1,268
  • 2
  • 9
  • 8
  • 7
    +1 for providing simple yet direct answer to the question asked – mloskot Jan 15 '13 at 12:53
  • 1
    This feature is available to older version of Python using `pip install ordereddict` and then changing the import line into `from ordereddict import OrderedDict` as stated on [this answer](http://stackoverflow.com/a/6852800/892951) (tested on Python 2.6.6). – chirale Dec 16 '13 at 09:46
  • Nice... but note, surprisingly, while this works for json 2.0.9 it does not work (i.e. order is not preserved in serialization) with simplejson 2.0.9 (that is supposedly just the externally installed version of json?!). Python version is 2.7.3. – Mario Ruggier Oct 08 '14 at 05:07
58

You are storing your values into a Python dict which has no inherent notion of ordering at all, it's just a key-to-value map. So your items lose all ordering when you place them into the values variable.

In fact the only way to get a deterministic ordering would be to use sort_keys=True, which I assume places them in alphanumeric ordering. Why is the order so important?

Michael
  • 8,362
  • 6
  • 61
  • 88
Joseph Lisee
  • 3,439
  • 26
  • 21
  • because i think that my code doesn't work because the order is not the right. is it possible? – elledienne May 05 '10 at 15:53
  • 9
    You code is working fine, its just that the order is undefined. If you want to always be consistent use "sort_keys=True". – Joseph Lisee May 05 '10 at 15:56
  • 6
    what if i want to sort by values rather than keys ? – Raunak Dugar Jun 17 '15 at 10:50
  • 2
    There is at least one very-valid reason to want to sort these: if you want to hash the dictionary to quickly determine later if a dictionary is identical but can't store the original dictionary, you need a deterministic representation of the dictionary. – iAdjunct Sep 12 '17 at 13:46
  • 4
    Note that [since Python 3.7, `dict` remembers their insertion order by default](https://docs.python.org/3/library/collections.html#ordereddict-objects). – user202729 Nov 04 '20 at 13:55
17

An OrderedDict as discussed elsewhere is most of the solution to your problem, and an 'ObjDict' could be even better.

However if you need the order maintained on loading, then you will also need the json.loads() to load the values into an OrderedDict. To do this use

from collections import OrderedDict
values=json.loads(jsontext,object_pairs_hook=OrderedDict)

Otherwise even though the json file will be in order, that order will be lost when loaded.

Perhaps an even better solution is to use 'ObjDict' in place of OrderedDict. This requires a pip install objdict. ObjDict still maintains order, as with OrderedDict, but also brings JSON support and better handling of this example.

from objdict import ObjDict
values = ObjDict("""{"profile" : "testprofile",
      "format": "RSA_RC4_Sealed" }""")
values.enc_key = base64.b64encode(chiave_da_inviare)
values.request = base64.b64encode(data)

values_json = values.dumps(separators=(',', ':'))
innov8
  • 2,093
  • 2
  • 24
  • 31
8

If you specify sort_keys=False then Python will simply print the items in whatever order they appear in the underlying Python dict object. In some cases this may happen to be the same as the default alphanumeric sort order. In your example, the keys AREN'T even sorted like that, since "format" comes after "request". Regardless, the sort_keys parameter is still valid, as evidenced by this sample code:

>>> import json
>>> json.dumps({"a":5, "b":6, "c":7}, sort_keys=False)
'{"a": 5, "c": 7, "b": 6}'
Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
6

You can sort json data using simple json.dumps as

sorted_json = json.dumps(values, sort_keys=True)

If you want no need to sort simply provide

unsorted_json = json.dumps(values)  

or:

unsorted_json = json.dumps(values, sort_keys=False)
Community
  • 1
  • 1
Praveen
  • 93
  • 1
  • 2
5

The keys aren't sorted: "profile", "enc_key", "request", "format".

It sounds like you want them to appear in the same order that you created them in the dictionary, but dictionaries are inherently unsorted, they don't remember the order you inserted keys.

There are a number of SortedDict implementations that you can use, but the json encoder won't know to use it to get the keys in the order you want.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662