How to convert JSON data into a Python object? How to convert JSON data into a Python object? django django

How to convert JSON data into a Python object?


UPDATE

With Python3, you can do it in one line, using SimpleNamespace and object_hook:

import jsonfrom types import SimpleNamespacedata = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'# Parse JSON into an object with attributes corresponding to dict keys.x = json.loads(data, object_hook=lambda d: SimpleNamespace(**d))print(x.name, x.hometown.name, x.hometown.id)

OLD ANSWER (Python2)

In Python2, you can do it in one line, using namedtuple and object_hook (but it's very slow with many nested objects):

import jsonfrom collections import namedtupledata = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'# Parse JSON into an object with attributes corresponding to dict keys.x = json.loads(data, object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))print x.name, x.hometown.name, x.hometown.id

or, to reuse this easily:

def _json_object_hook(d): return namedtuple('X', d.keys())(*d.values())def json2obj(data): return json.loads(data, object_hook=_json_object_hook)x = json2obj(data)

If you want it to handle keys that aren't good attribute names, check out namedtuple's rename parameter.


Check out the section titled Specializing JSON object decoding in the json module documentation. You can use that to decode a JSON object into a specific Python type.

Here's an example:

class User(object):    def __init__(self, name, username):        self.name = name        self.username = usernameimport jsondef object_decoder(obj):    if '__type__' in obj and obj['__type__'] == 'User':        return User(obj['name'], obj['username'])    return objjson.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}',           object_hook=object_decoder)print type(User)  # -> <type 'type'>

Update

If you want to access data in a dictionary via the json module do this:

user = json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}')print user['name']print user['username']

Just like a regular dictionary.


This is not code golf, but here is my shortest trick, using types.SimpleNamespace as the container for JSON objects.

Compared to the leading namedtuple solution, it is:

  • probably faster/smaller as it does not create a class for each object
  • shorter
  • no rename option, and probably the same limitation on keys that are not valid identifiers (uses setattr under the covers)

Example:

from __future__ import print_functionimport jsontry:    from types import SimpleNamespace as Namespaceexcept ImportError:    # Python 2.x fallback    from argparse import Namespacedata = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'x = json.loads(data, object_hook=lambda d: Namespace(**d))print (x.name, x.hometown.name, x.hometown.id)