How to Get Json to Load into an Ordereddict

Can I get JSON to load into an OrderedDict?

Yes, you can. By specifying the object_pairs_hook argument to JSONDecoder. In fact, this is the exact example given in the documentation.

>>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
OrderedDict([('foo', 1), ('bar', 2)])
>>>

You can pass this parameter to json.loads (if you don't need a Decoder instance for other purposes) like so:

>>> import json
>>> from collections import OrderedDict
>>> data = json.loads('{"foo":1, "bar": 2}', object_pairs_hook=OrderedDict)
>>> print json.dumps(data, indent=4)
{
"foo": 1,
"bar": 2
}
>>>

Using json.load is done in the same way:

>>> data = json.load(open('config.json'), object_pairs_hook=OrderedDict)

json.loads() doesn't keep order

Both JSON en Python dictionaries (those are JSON objects) are unordered. So in fact it does not makes any sense to do that, because the JSON encoder can change the order.

You can however define a custom JSON decoder, and then parse it with that decoder. So here the dictionary hook willl be an OrderedDict:

from json import JSONDecoder
from collections import OrderedDict

customdecoder = JSONDecoder(object_pairs_hook=OrderedDict)

Then you can decode with:

customdecoder.decode(your_json_string)

This will thus store the items in an OrderedDict instead of a dictionary. But be aware - as said before - that the order of the keys of JSON objects is unspecified.

Alternatively, you can also pass the hook to the loads function:

from json import loads
from collections import OrderedDict

loads(your_json_string, object_pairs_hook=OrderedDict)

Update: as of python-3.7, a dictionary retains insertion order. So if one uses python-3.7, the standard json.load and json.loads should work fine. Note however that a JSON object is still unordered, so that the JavaScript end can load/dump the object in any order.

Json to OrderedDict in Python

You have the keyword argument in the wrong place, which may be clearer if we add more whitespace:

data = OrderedDict(
json.loads(
resp.read().decode("utf-8") # one argument to json.loads
),
object_pairs_hook=OrderedDict # second argument to OrderedDict
)

OrderedDict takes no such argument - you meant to pass it to json.loads, then you don't need to re-create it:

data = json.loads(
resp.read().decode("utf-8"),
object_pairs_hook=OrderedDict
)

The reason you aren't seeing the order you want when you leave out the object_pairs_hook is that json.loads is creating a vanilla, unordered dictionary then converting it to an OrderedDict.

Python json.loads changes the order of the object

Dictionaries (objects) in python have no guaranteed order. So when parsed into a dict, the order is lost.

If the order is important for some reason, you can have json.loads use an OrderedDict instead, which is like a dict, but the order of keys is saved.

from collections import OrderedDict

data_content = json.loads(input_data.decode('utf-8'), object_pairs_hook=OrderedDict)

How do I update my dictionary with values from JSON?

Instead of processing the data after it has been loaded - you can pass custom functions to json.load / loads which can simplify extraction:

ordered_keys = ("leaveGroup", "functionalCode", "DFASUnionCode", "normalHours")
order_dic_keys = OrderedDict.fromkeys(ordered_keys)

def extract_data(obj):
for key, value in obj:
if key in order_dic_keys:
order_dic_keys[key] = value

>>> json.loads(data, object_pairs_hook=extract_data)
>>> order_dic_keys
OrderedDict([('leaveGroup', '2'),
('functionalCode', '00'),
('DFASUnionCode', None),
('normalHours', 80)])

full code example:

import json
from collections import OrderedDict

def extract_data(obj):
for key, value in obj:
if key in order_dic_keys:
order_dic_keys[key] = value
return dict(obj)

ordered_keys = ("leaveGroup", "functionalCode", "DFASUnionCode", "normalHours")
order_dic_keys = OrderedDict.fromkeys(ordered_keys)

with open("file.json") as f:
json_file = json.load(f, object_pairs_hook=extract_data)

print(order_dic_keys)

understanding object_pairs_hook in json.loads()

It allows you to customize what objects your JSON will parse into. For this specific argument (object_pairs_hook) it's for pair (read key/value pairs of a mapping object).

For instance if this string appears in your JSON:

{"var1": "val1", "var2": "val2"}

It will call the function pointed to with the following argument:

[('var1', 'val1'), ('var2', 'val2')]

Whatever the function returns is what will be used in the resulting parsed structure where the above string was.

A trivial example is object_pairs_hook=collections.OrderedDict which ensures your keys to be ordered the same way as they were they occurred in the incoming string.

The generic idea of a hook is to allow you to register a function that is called (back) as needed for a given task. In this specific case it allows you to customize decoding of (different types of objects in the) incoming JSON string.



Related Topics



Leave a reply



Submit