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?

7voto

danilo Punkte 4992

Verbesserung der sehr guten Antwort von lovasoa.

Wenn Sie Python 3.6+ verwenden, können Sie verwenden:
pip install marshmallow-enum und
pip install marshmallow-dataclass

Es ist einfach und typsicher.

Sie können Ihre Klasse in einen string-json umwandeln und umgekehrt:

Von Objekt zu String Json:

    from marshmallow_dataclass import dataclass
    user = User("Danilo","50","RedBull",15,OrderStatus.CREATED)
    user_json = User.Schema().dumps(user)
    user_json_str = user_json.data

Von String Json zu Object:

    json_str = '{"name":"Danilo", "orderId":"50", "productName":"RedBull", "quantity":15, "status":"Created"}'
    user, err = User.Schema().loads(json_str)
    print(user,flush=True)

Klassendefinitionen:

class OrderStatus(Enum):
    CREATED = 'Created'
    PENDING = 'Pending'
    CONFIRMED = 'Confirmed'
    FAILED = 'Failed'

@dataclass
class User:
    def __init__(self, name, orderId, productName, quantity, status):
        self.name = name
        self.orderId = orderId
        self.productName = productName
        self.quantity = quantity
        self.status = status

    name: str
    orderId: str
    productName: str
    quantity: int
    status: OrderStatus

6voto

JSON zu Python-Objekt

Der folgende Code erstellt rekursiv dynamische Attribute mit den Schlüsseln der Objekte.

JSON-Objekt - fb_data.json :

{
    "name": "John Smith",
    "hometown": {
        "name": "New York",
        "id": 123
    },
    "list": [
        "a",
        "b",
        "c",
        1,
        {
            "key": 1
        }
    ],
    "object": {
        "key": {
            "key": 1
        }
    }
}

Bei der Umwandlung haben wir 3 Fälle:

  • Listen
  • dicts (neues Objekt)
  • bool, int, float und str

    import json

    class AppConfiguration(object): def init(self, data=None): if data is None: with open("fb_data.json") as fh: data = json.loads(fh.read()) else: data = dict(data)

        for key, val in data.items():
            setattr(self, key, self.compute_attr_value(val))
    
    def compute_attr_value(self, value):
        if isinstance(value, list):
            return [self.compute_attr_value(x) for x in value]
        elif isinstance(value, dict):
            return AppConfiguration(value)
        else:
            return value

    if name == "main": instance = AppConfiguration()

    print(instance.name)
    print(instance.hometown.name)
    print(instance.hometown.id)
    print(instance.list[4].key)
    print(instance.object.key.key)

Die Schlüssel-Wert-Paare sind nun Attribute - Objekte.

Ausgabe:

John Smith
New York
123
1
1

JSON als Code einfügen

Unterstützt TypeScript , Python , Go , Ruby , C# , Java , Swift , Rust , Kotlin , C++ , Flow , Objective-C , JavaScript , Elm y JSON Schema .

  • Interaktive Generierung von Typen und (De-)Serialisierungscode aus JSON, JSON Schema und TypeScript
  • JSON/JSON-Schema/TypeScript als Code einfügen

enter image description here

quicktype leitet aus JSON-Beispieldaten Typen ab und gibt dann stark typisierte Modelle und Serialisierer für die Arbeit mit diesen Daten in Ihrer gewünschten Programmiersprache aus.

Ausgabe:

# Generated by https://quicktype.io
#
# To change quicktype's target language, run command:
#
#   "Set quicktype target language"

from typing import List, Union

class Hometown:
    name: str
    id: int

    def __init__(self, name: str, id: int) -> None:
        self.name = name
        self.id = id

class Key:
    key: int

    def __init__(self, key: int) -> None:
        self.key = key

class Object:
    key: Key

    def __init__(self, key: Key) -> None:
        self.key = key

class FbData:
    name: str
    hometown: Hometown
    list: List[Union[Key, int, str]]
    object: Object

    def __init__(self, name: str, hometown: Hometown, list: List[Union[Key, int, str]], object: Object) -> None:
        self.name = name
        self.hometown = hometown
        self.list = list
        self.object = object

Diese Erweiterung ist kostenlos erhältlich in der Visual Studio Code-Marktplatz .

5voto

sebpiq Punkte 7172

Ich habe ein kleines (De-)Serialisierungs-Framework geschrieben, das any2any die bei der Durchführung komplexer Transformationen zwischen zwei Python-Typen hilft.

In Ihrem Fall wollen Sie wohl von einem Wörterbuch (das Sie mit json.loads ) zu einem komplexen Objekt response.education ; response.name mit einer verschachtelten Struktur response.education.id , etc ... Das ist also genau das, wofür dieses Framework gemacht ist. Die Dokumentation ist noch nicht sehr umfangreich, aber durch die Verwendung von any2any.simple.MappingToObject sollten Sie das sehr leicht tun können. Bitte fragen Sie, wenn Sie Hilfe benötigen.

5voto

lestat_kim Punkte 355

Die leichteste Lösung ist meiner Meinung nach

import orjson  # faster then json =)
from typing import NamedTuple

_j = '{"name":"","age":37,"mother":{"name":"","age":58},"children":["","",""],"married": true,' \
     '"dog":null} '

class PersonNameAge(NamedTuple):
    name: str
    age: int

class UserInfo(NamedTuple):
    name: str
    age: int
    mother: PersonNameAge
    children: list
    married: bool
    dog: str

j = json.loads(_j)
u = UserInfo(**j)

print(u.name, u.age, u.mother, u.children, u.married, u.dog)

>>> Ivan 37 {'name': 'Olga', 'age': 58} ['Mary', 'Igor', 'Jane'] True None

4voto

tmoschou Punkte 855

Wenn Sie auf der Suche nach einer typsicheren Deserialisierung von JSON oder einem komplexen Diktat in eine Python-Klasse sind, empfehle ich dringend pydantisch für Python 3.7+. Nicht nur, dass es eine prägnante API hat (erfordert nicht das Schreiben von "Helper" Boilerplate), kann mit Python integrieren Datenklassen verfügt jedoch über eine statische und Laufzeit-Typüberprüfung komplexer und verschachtelter Datenstrukturen.

Beispiel für die Verwendung:

from pydantic import BaseModel
from datetime import datetime

class Item(BaseModel):
    field1: str | int           # union
    field2: int | None = None   # optional
    field3: str = 'default'     # default values

class User(BaseModel):
    name: str | None = None
    username: str
    created: datetime           # default type converters
    items: list[Item] = []      # nested complex types

data = {
    'name': 'Jane Doe',
    'username': 'user1',
    'created': '2020-12-31T23:59:00+10:00',
    'items': [
        {'field1': 1, 'field2': 2},
        {'field1': 'b'},
        {'field1': 'c', 'field3': 'override'}
    ]
}

user: User = User(**data)

Weitere Details und Funktionen finden Sie auf pydantic's rational Abschnitt in ihrer Dokumentation.

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