494 Stimmen

Wie konvertiert man JSON-Daten in ein Python-Objekt?

Ich möchte JSON-Daten in ein Python-Objekt konvertieren.

Ich erhalte JSON-Datenobjekte von der Facebook-API, die ich in meiner Datenbank speichern möchte.

Meine aktuelle Ansicht in Django (Python) ( request.POST enthält das JSON):

response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()
  • Das funktioniert gut, aber wie kann ich komplexe JSON-Datenobjekte behandeln?
  • Wäre es nicht viel besser, wenn ich dieses JSON-Objekt irgendwie in ein Python-Objekt konvertieren könnte, um es einfach zu verwenden?

685voto

DS. Punkte 20324

UPDATE

Mit Python3 können Sie dies in einer Zeile tun, indem Sie SimpleNamespace y object_hook :

import json
from types import SimpleNamespace

data = '{"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)

ALTE ANTWORT (Python2)

In Python2 können Sie dies in einer Zeile tun, indem Sie namedtuple y object_hook (aber bei vielen verschachtelten Objekten ist es sehr langsam):

import json
from collections import namedtuple

data = '{"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

oder, um diese einfach wiederzuverwenden:

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)

Wenn Sie möchten, dass es mit Schlüsseln umgeht, die keine guten Attributnamen sind, sehen Sie sich namedtuple 's rename Parameter .

182voto

cmaluenda Punkte 1639

Sie könnten dies versuchen:

class User(object):
    def __init__(self, name, username):
        self.name = name
        self.username = username

import json
j = json.loads(your_json)
u = User(**j)

Erstellen Sie einfach ein neues Objekt, und übergeben Sie die Parameter als Map.


Sie können auch ein JSON mit Objekten haben:

import json
class 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)

144voto

Shakakai Punkte 3505

Sehen Sie sich den Abschnitt Spezialisierung der Dekodierung von JSON-Objekten en el json Modul-Dokumentation . Damit können Sie ein JSON-Objekt in einen bestimmten Python-Typ dekodieren.

Hier ist ein Beispiel:

class User(object):
    def __init__(self, name, username):
        self.name = name
        self.username = username

import json
def object_decoder(obj):
    if '__type__' in obj and obj['__type__'] == 'User':
        return User(obj['name'], obj['username'])
    return obj

json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}',
           object_hook=object_decoder)

print type(User)  # -> <type 'type'>

Update

Wenn Sie über das json-Modul auf Daten in einem Wörterbuch zugreifen möchten, tun Sie dies:

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

Genau wie ein normales Wörterbuch.

113voto

eddygeek Punkte 3725

Dies ist kein Code-Golf, aber hier ist mein kürzester Trick, der types.SimpleNamespace als Container für JSON-Objekte.

Verglichen mit den führenden namedtuple Lösung, ist es:

  • wahrscheinlich schneller/kleiner, da nicht für jedes Objekt eine Klasse erstellt wird
  • kürzer
  • keine rename und wahrscheinlich die gleiche Einschränkung für Schlüssel, die keine gültigen Bezeichner sind (verwendet setattr unter der Bettdecke)

from __future__ import print_function
import json

try:
    from types import SimpleNamespace as Namespace
except ImportError:
    # Python 2.x fallback
    from argparse import Namespace

data = '{"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)

44voto

ubershmekel Punkte 10402

Hier ist eine schnelle und schmutzige json pickle Alternative

import json

class User:
    def __init__(self, name, username):
        self.name = name
        self.username = username

    def to_json(self):
        return json.dumps(self.__dict__)

    @classmethod
    def from_json(cls, json_str):
        json_dict = json.loads(json_str)
        return cls(**json_dict)

# example usage
User("tbrown", "Tom Brown").to_json()
User.from_json(User("tbrown", "Tom Brown").to_json()).to_json()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X