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.
You could try this:
class User(object): def __init__(self, name, username): self.name = name self.username = usernameimport jsonj = json.loads(your_json)u = User(**j)
Just create a new object, and pass the parameters as a map.
Note: It does not work for nested classes.
You can have a JSON with objects too:
import jsonclass Address(object): def __init__(self, street, number): self.street = street self.number = number def __str__(self): return "{0} {1}".format(self.street, self.number)class User(object): def __init__(self, name, address): self.name = name self.address = Address(**address) def __str__(self): return "{0} ,{1}".format(self.name, self.address)if __name__ == '__main__': js = '''{"name":"Cristian", "address":{"street":"Sesame","number":122}}''' j = json.loads(js) print(j) u = User(**j) print(u)