1

How do I convert an OrderedDict to a normal dictionary while preserving the same order?

The reason I am asking this is because is when I fetch my data from an API, I get a JSON string, in which I use json.loads(str) to return a dictionary. This dictionary that is returned from json.loads(...) is just out of order and is randomly ordered. Also, I've read that OrderedDict is slow to work with so I want to use regular dict in same order as original JSON string.

Slightly off-topic: Is there anyway to convert a JSON string to a dict using json.loads(...) while maintaining the same order without using collections.OrderedDict?

martineau
  • 119,623
  • 25
  • 170
  • 301
user1757703
  • 2,925
  • 6
  • 41
  • 62

2 Answers2

6

Update: As of Python 3.6, builtin dicts behave like OrderedDict. That is, they preserve insertion order.


When you convert an OrderedDict to a normal dict, you can't guarantee the ordering will be the preserved, because dicts are unordered. Which is why OrderedDict exists in the first place.

It seems like you're trying to have your cake and eat it too, here. If you want the order of the JSON string preserved, use the answer from the question I linked to in the comments to load your json string directly into an OrderedDict. But you have to deal with whatever performance penalty that carries (I don't know offhand what that penalty is. It may even be neglible for you use-case.). If you want the best possible performance, just use dict. But it's going to be unordered.

Stuart Berg
  • 17,026
  • 12
  • 67
  • 99
dano
  • 91,354
  • 19
  • 222
  • 219
  • I see, okay. Thank You. I can use the OrderedDict but I'd rather not sacrifice performance for it. – user1757703 May 31 '14 at 02:50
  • 1
    @user1757703 I'd do some tests on your workload and compare how the two perform. You may be worrying over a very small difference. Or maybe it's huge, but you won't know until you try. Unfortunately I don't think you have much choice but to take the hit if you absolutely need to preserve ordering. – dano May 31 '14 at 02:51
  • I'm up-voting your answer, but mostly because of the link in your comment under the question since the question is really about preserving the order of key/value pairs in a JSON object—perhaps you should move the comment into your answer for one-stop-shopping. – martineau Aug 22 '16 at 18:07
1

Both JSON objects and Python dicts are unordered. To preserve order, use JSON arrays which are mapped to Python lists. Elements of JSON arrays should be JSON objects. These will be mapped to Python lists of Python dicts.

Python 3:

from collections import OrderedDict
import json

# Preserving order in Python dict:
ordered_dict = OrderedDict([
    ('a', 1),
    ('b', 2),
    ('c', 3),
])

# Convert to JSON while preserving order:
ordered_list = [{key: val} for key, val in ordered_dict.items()]
json.dumps(ordered_list)
# '[{"a": 1}, {"b": 2}, {"c": 3}]'

Javascript (JSON):

var orderedListStr = '[{"a": 1}, {"b": 2}, {"c": 3}]';
// We will receive this array of objects with preserved order:
var orderedList = JSON.parse(orderedListStr)
Dmitriy Sintsov
  • 3,821
  • 32
  • 20
  • True, JSON objects are defined to be unordered sets of name/value pairs, however the pairs do appear in some order and it's conceivable that one would want to preserve it for various reasons. It unclear from the suggestion in your answer how exactly one would convert a JSON object into an array or list that did this. – martineau Aug 22 '16 at 18:03
  • That's a definite improvement. Unfortunately the question is about producing a dictionary, not a list (_all_ lists are ordered, btw). I also see no value in converting to a list of one-element dictionaries vs a list of tuples (i.e. `[(key, val) for key, val in ordered_dict.items()]`). Furthermore, having to use a list in place of dictionary could have serious performance implications since look-ups would become much slower (O(n) vs O(1)). Up-voting anyway for thinking outside the box. `;-)` – martineau Aug 24 '16 at 18:01
  • I agree that not having ordered dictionary (object) for JSON is not a well thought-out decision. But these things are out of our control. Javascript is a bit inferior than Python in these matters not offering built-in type for ordered dictionaries. While these elements of lists are one-element dictionaries, the values can be quite complex and even nested with the same list ordering approach. Django recently moves from tuples to lists because tests showed they have the same speed but lists are more flexible. – Dmitriy Sintsov Aug 25 '16 at 09:21
  • At Javascript client-side I sometimes keep both such ordered arrays and restore these to usual unordered Javascript objects. It will use double memory however allows both possibilities: to iterate array with proper order and to directly access values by hashed object. Memory is cheap. – Dmitriy Sintsov Aug 25 '16 at 09:35
  • Seems like all you would need to do is keep an ordered list/array of the just the keys to know their order—which wouldn't require double the memory. In fact, that's how some implemented their own `OrderedDict` before it was added to the standard library in Python 2.4. – martineau Aug 25 '16 at 13:02
  • That's true. Just ordered_dict.keys() should work fine. My approach still probably will save a bit of memory and HTTP bandwitch but O(n). – Dmitriy Sintsov Aug 25 '16 at 16:13