1

When working with simplejson in Django, I sometimes need to send the information strictly in order.

values = {"entry1":"value1","entry2":"value2","entry3":"value3"}
return HttpResponse(simplejson.dumps(values),content_type="application/json")

That's what it returns

{"entry2": "value2", "entry3": "value3", "entry1": "value1"}

But I want it to returns this instead:

{"entry1":"value1","entry2":"value2","entry3":"value3"}

How can I send the information in order in simplejson?

zurfyx
  • 31,043
  • 20
  • 111
  • 145

4 Answers4

3

I sometimes need to send the information strictly in order.

Don't use a dictionary then, use a list of tuples:

values = [("entry1", "value1"), ("entry2", "value2"), ("entry3", "value3")]

Dictionaries and JSON objects do not have a set order. Neither will preserve your input order, nor are they required to.

To quote the JSON RFC:

An object is an unordered collection of zero or more name/value pairs [...]

and the Python dict.items() documentation:

Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • @jh314 answer seems to be working as well. What's more advisable? Using a list or `sort_keys=True`? – zurfyx Jul 22 '13 at 14:04
  • @Jerry: If you need the keys to be returned in sorted order, then use `sort_keys`. **However**, that does not guarantee that the consumer of the JSON data will not ignore the order of the object keys. If order is important, then use a list as it preserves order. – Martijn Pieters Jul 22 '13 at 14:06
  • @Jerry: If your keys are *not* provided in sorted order, then `sort_keys` will still alter the ordering for you, of course. `{'foo': 1, 'bar': 2, 'eggs': 'ham'}` will be returned in the order `bar`, `eggs`, `foo` for example. – Martijn Pieters Jul 22 '13 at 14:07
  • 2
    As a footnote, the main point of `sort_keys` is to generate stable output (e.g. for testing, or to avoid nuking caches etc -- extra important in recent Python versions that use a random hash seed), not to deal with decoders that don't implement the JSON spec correctly. If you control both sides of your application, fix the consumer. – Fredrik Jul 22 '13 at 22:01
  • **This shouldn't be the accepted answer.** JSON objects do have a set order, namely as defined by the ordering of the elements. You're correct in that Python's `dict` doesn't have a guaranteed ordering, however `OrderedDict` does. See @pygeek's answer for how it can be used. – Bouke Jul 23 '13 at 07:30
  • @bouke: the [JSON RFC](http://www.ietf.org/rfc/rfc4627.txt) disagrees with you: *An object is an unordered collection of zero or more name/value pairs*. Do *not* confuse the order of a single serialisation with a set ordering. The client that deserialises on the other side is perfectly in its right to *ignore* that order. – Martijn Pieters Jul 23 '13 at 07:52
  • @MartijnPieters ah thanks, I stand corrected. – Bouke Jul 23 '13 at 08:00
2

The traditional way of solving this issue is by using 2-dimensional tuple/list, as suggested by Martjin Pieters.

The more Pythonic way of accomplishing this is by using OrderedDict, however.

For similar question/solution see: Can I get JSON to load into an OrderedDict in Python?

For OrderedDict documentation see: http://docs.python.org/2/library/collections.html#collections.OrderedDict

Community
  • 1
  • 1
pygeek
  • 7,356
  • 1
  • 20
  • 41
1

You can use the sort_keys=True option in dumps:

simplejson.dumps(values, sort_keys=True)

which will print out your dictionary with the keys in sorted order. However, dictionaries are inherently unordered, so when you give the dictionary as a parameter to HttpResponse, the results won't be in order.

jh314
  • 27,144
  • 16
  • 62
  • 82
0

This not problem with simplejson, its the behavior of dict in python. dicts are not ordered, so you can't really predict in what order they will come.

You can reformat your data to get that in order as:

values = [ {"entry1":"value1"}, { "entry2":"value2"} ,{"entry3":"value3"} ]

or

values = [ {"key":"entry1", "value":"value1"},
           {"key":"entry2", "value":"value2"},
           {"key":"entry3", "value":"value3"}
         ]
Rohan
  • 52,392
  • 12
  • 90
  • 87
  • Well, it's not just dicts -- JSON objects are unordered so an implementation that relies on order when reading is broken. From http://www.ietf.org/rfc/rfc4627.txt: "An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array." – Fredrik Jul 22 '13 at 14:15