Arbeiten mit JSON-Daten in Python

Arbeiten mit JSON-Daten in Python

JSON ist seit seiner Gründung schnell zum De-facto-Standard für den Informationsaustausch geworden. Möglicherweise sind Sie hier, weil Sie einige Daten von hier nach dort transportieren müssen. Möglicherweise erfassen Sie Informationen überAPI oder speichern Ihre Daten indocument database. Auf die eine oder andere Weise sind Sie in JSON bis zum Hals und müssen Python aus dem Weg räumen.

Glücklicherweise ist dies eine ziemlich häufige Aufgabe, und - wie bei den meisten gängigen Aufgaben - macht Python es fast ekelhaft einfach. Hab keine Angst, andere Pythoneer und Pythonisten. Das wird ein Kinderspiel!

So, we use JSON to store and exchange data? Ja, du hast es verstanden! Es ist nichts weiter als ein standardisiertes Format, mit dem die Community Daten weitergibt. Denken Sie daran, dass JSON nicht das einzige Format ist, das für diese Art von Arbeit verfügbar ist, aberXML undYAML sind wahrscheinlich die einzigen anderen, die es wert sind, in einem Atemzug erwähnt zu werden.

Kostenloser PDF-Download: Python 3 Spickzettel

Eine (sehr) kurze Geschichte von JSON

Es überrascht nicht, dassJavaScriptObjectNotation von einer Teilmenge der JavaScript-Programmiersprache inspiriert wurde, die sich mit der Objektliteralsyntax befasst. Sie haben einnifty website, das das Ganze erklärt. Keine Sorge: JSON ist längst sprachunabhängig geworden und existiert alsits own standard. Daher können wir JavaScript für diese Diskussion dankenswerterweise vermeiden.

Letztendlich hat die Community JSON übernommen, da es sowohl für Menschen als auch für Maschinen einfach ist, JSON zu erstellen und zu verstehen.

Schau, es ist JSON!

Sich fertig machen. Ich werde Ihnen JSON aus dem wirklichen Leben zeigen - genau wie Sie es in freier Wildbahn sehen würden. Es ist in Ordnung: JSON soll für jeden lesbar sein, der eine Sprache im C-Stil verwendet, und Python ist eine Sprache im C-Stil.

{
    "firstName": "Jane",
    "lastName": "Doe",
    "hobbies": ["running", "sky diving", "singing"],
    "age": 35,
    "children": [
        {
            "firstName": "Alice",
            "age": 6
        },
        {
            "firstName": "Bob",
            "age": 8
        }
    ]
}

Wie Sie sehen können, unterstützt JSON primitive Typen wie Zeichenfolgen und Zahlen sowie verschachtelte Listen und Objekte.

Wait, that looks like a Python dictionary! Ich weiß, richtig? Es ist zu diesem Zeitpunkt eine ziemlich universelle Objektnotation, aber ich denke nicht, dass UON so gut von der Zunge rollt. Fühlen Sie sich frei, Alternativen in den Kommentaren zu diskutieren.

Wütend! Sie haben Ihre erste Begegnung mit wildem JSON überlebt. Jetzt müssen Sie nur noch lernen, wie man es zähmt.

Python unterstützt JSON nativ!

Python wird mit einem integrierten Paket namensjson zum Codieren und Decodieren von JSON-Daten geliefert.

Wirf diesen kleinen Kerl einfach oben in deine Akte:

import json

Ein kleiner Wortschatz

Der Prozess der Codierung von JSON wird normalerweise alsserialization bezeichnet. Dieser Begriff bezieht sich auf die Umwandlung von Daten inseries of bytes (daherserial), die über ein Netzwerk gespeichert oder übertragen werden sollen. Möglicherweise hören Sie auch den Begriffmarshaling, aber das ista whole other discussion. deserialization ist natürlich der wechselseitige Prozess zum Decodieren von Daten, die im JSON-Standard gespeichert oder geliefert wurden.

Yikes! That sounds pretty technical. Auf jeden Fall. In Wirklichkeit geht es hier jedoch nur umreading undwriting. Stellen Sie sich das so vor:encoding steht fürwriting Daten auf der Festplatte, währenddecoding fürreading Daten im Speicher steht.

JSON serialisieren

Was passiert, nachdem ein Computer viele Informationen verarbeitet hat? Es muss ein Datendump erstellt werden. Dementsprechend macht diejson-Bibliothek diedump()-Methode zum Schreiben von Daten in Dateien verfügbar. Es gibt auch einedumps()-Methode (ausgesprochen als "dump-s") zum Schreiben in eine Python-Zeichenfolge.

Einfache Python-Objekte werden gemäß einer ziemlich intuitiven Konvertierung in JSON übersetzt.

Python JSON

dict

object

list,tuple

array

str

string

int,long,float

number

True

true

False

false

None

null

Ein einfaches Serialisierungsbeispiel

Stellen Sie sich vor, Sie arbeiten mit einem Python-Objekt im Speicher, das ungefähr so ​​aussieht:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

Es ist wichtig, dass Sie diese Informationen auf der Festplatte speichern. Daher besteht Ihre Aufgabe darin, sie in eine Datei zu schreiben.

Mit dem Kontextmanager von Python können Sie eine Datei mit dem Namendata_file.json erstellen und im Schreibmodus öffnen. (JSON-Dateien enden bequemerweise mit der Erweiterung.json.)

with open("data_file.json", "w") as write_file:
    json.dump(data, write_file)

Beachten Sie, dassdump() zwei Positionsargumente akzeptiert: (1) das zu serialisierende Datenobjekt und (2) das dateiähnliche Objekt, in das die Bytes geschrieben werden.

Wenn Sie diese serialisierten JSON-Daten weiterhin in Ihrem Programm verwenden möchten, können Sie sie auch in ein natives Pythonstr-Objekt schreiben.

json_string = json.dumps(data)

Beachten Sie, dass das dateiähnliche Objekt nicht vorhanden ist, da Sie nicht tatsächlich auf die Festplatte schreiben. Davon abgesehen istdumps() genau wiedump().

Hurra! Sie haben ein Baby-JSON geboren und sind bereit, es in die Wildnis zu entlassen, um groß und stark zu werden.

Einige nützliche Schlüsselwortargumente

Denken Sie daran, dass JSON für Menschen leicht lesbar sein soll, aber lesbare Syntax reicht nicht aus, wenn alles zusammengedrückt ist. Außerdem haben Sie wahrscheinlich einen anderen Programmierstil als ich und es ist möglicherweise einfacher für Sie, Code zu lesen, wenn er nach Ihren Wünschen formatiert ist.

NOTE: Sowohl die Methodendump() als auchdumps()verwenden dieselben Schlüsselwortargumente.

Die erste Option, die die meisten Menschen ändern möchten, ist Leerzeichen. Mit dem Schlüsselwortargumentindentkönnen Sie die Einrückungsgröße für verschachtelte Strukturen angeben. Überzeugen Sie sich selbst von dem Unterschied, indem Siedata verwenden, die wir oben definiert haben, und die folgenden Befehle in einer Konsole ausführen:

>>>

>>> json.dumps(data)
>>> json.dumps(data, indent=4)

Eine weitere Formatierungsoption ist das Schlüsselwortargumentseparators. Standardmäßig ist dies ein 2-Tupel der Trennzeichenfolgen(", ", ": "), aber eine übliche Alternative für kompaktes JSON ist(",", ":"). Schauen Sie sich das JSON-Beispiel noch einmal an, um zu sehen, wo diese Trennzeichen ins Spiel kommen.

Es gibt andere, wiesort_keys, aber ich habe keine Ahnung, was dieser tut. Wenn Sie neugierig sind, finden Sie eine ganze Liste indocs.

JSON deserialisieren

Großartig, es sieht so aus, als hätten Sie sich einen wilden JSON eingefangen! Jetzt ist es Zeit, es in Form zu bringen. In der Bibliothekjson finden Sieload() undloads(), um JSON-codierte Daten in Python-Objekte umzuwandeln.

Genau wie bei der Serialisierung gibt es eine einfache Konvertierungstabelle für die Deserialisierung, obwohl Sie wahrscheinlich erraten können, wie sie bereits aussieht.

JSON Python

object

dict

array

list

string

str

number (int)

int

number (real)

float

true

True

false

False

null

None

Technisch gesehen ist diese Konvertierung keine perfekte Umkehrung zur Serialisierungstabelle. Das bedeutet im Grunde, dass Sie möglicherweise nicht genau dasselbe Objekt zurückerhalten, wenn Sie ein Objekt ab und zu codieren und es später erneut decodieren. Ich stelle mir vor, es ist ein bisschen wie Teleportation: Zerbrich meine Moleküle hier und setze sie dort wieder zusammen. Bin ich immer noch dieselbe Person?

In Wirklichkeit ist es wahrscheinlich eher so, als würde man einen Freund dazu bringen, etwas ins Japanische zu übersetzen, und einen anderen Freund, es wieder ins Englische zu übersetzen. Unabhängig davon wäre das einfachste Beispiel, eintuple zu codieren und einlist nach dem Decodieren zurückzugewinnen, wie folgt:

>>>

>>> blackjack_hand = (8, "Q")
>>> encoded_hand = json.dumps(blackjack_hand)
>>> decoded_hand = json.loads(encoded_hand)

>>> blackjack_hand == decoded_hand
False
>>> type(blackjack_hand)

>>> type(decoded_hand)

>>> blackjack_hand == tuple(decoded_hand)
True

Ein einfaches Deserialisierungsbeispiel

Stellen Sie sich diesmal vor, Sie haben einige Daten auf der Festplatte gespeichert, die Sie im Speicher bearbeiten möchten. Sie verwenden weiterhin den Kontextmanager, dieses Mal öffnen Sie jedoch die vorhandenendata_file.jsonim Lesemodus.

with open("data_file.json", "r") as read_file:
    data = json.load(read_file)

Die Dinge sind hier ziemlich einfach, aber denken Sie daran, dass das Ergebnis dieser Methode jeden der zulässigen Datentypen aus der Konvertierungstabelle zurückgeben kann. Dies ist nur wichtig, wenn Sie Daten laden, die Sie zuvor noch nicht gesehen haben. In den meisten Fällen ist das Stammobjektdict oderlist.

Wenn Sie JSON-Daten aus einem anderen Programm abgerufen oder auf andere Weise eine Zeichenfolge mit JSON-formatierten Daten in Python erhalten haben, können Sie diese problemlos mitloads() deserialisieren, das natürlich aus einer Zeichenfolge geladen wird:

json_string = """
{
    "researcher": {
        "name": "Ford Prefect",
        "species": "Betelgeusian",
        "relatives": [
            {
                "name": "Zaphod Beeblebrox",
                "species": "Betelgeusian"
            }
        ]
    }
}
"""
data = json.loads(json_string)

Voilà! Sie haben den wilden JSON gezähmt und jetzt ist er unter Ihrer Kontrolle. Aber was Sie mit dieser Kraft machen, liegt bei Ihnen. Sie könnten es füttern, pflegen und sogar Tricks beibringen. Es ist nicht so, dass ich dir nicht vertraue ... aber lass es an der Leine, okay?

Ein Beispiel aus der realen Welt

In Ihrem Einführungsbeispiel verwenden SieJSONPlaceholder, eine hervorragende Quelle für gefälschte JSON-Daten für Übungszwecke.

Erstellen Sie zuerst eine Skriptdatei mit dem Namenscratch.py oder was auch immer Sie möchten. Ich kann dich nicht wirklich aufhalten.

Sie müssen eine API-Anforderung an den JSONPlaceholder-Service senden. Verwenden Sie daher einfach das Paketrequests, um das schwere Heben durchzuführen. Fügen Sie diese Importe oben in Ihrer Datei hinzu:

import json
import requests

Jetzt werden Sie mit einer Liste von TODOs arbeiten, denn ... Sie wissen, es ist ein Übergangsritus oder was auch immer.

Stellen Sie eine Anfrage an die JSONPlaceholder-API für den Endpunkt/todos. Wenn Sie mitrequests nicht vertraut sind, gibt es tatsächlich eine praktischejson()-Methode, die die gesamte Arbeit für Sie erledigt. Sie können jedoch üben, diejson-Bibliothek zu verwenden, umtextzu deserialisieren ) s Attribut des Antwortobjekts. Es sollte ungefähr so ​​aussehen:

response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos = json.loads(response.text)

Sie glauben nicht, dass dies funktioniert? Führen Sie die Datei im interaktiven Modus aus und testen Sie sie selbst. Überprüfen Sie währenddessen den Typ vontodos. Wenn Sie sich abenteuerlustig fühlen, werfen Sie einen Blick auf die ersten 10 Elemente in der Liste.

>>>

>>> todos == response.json()
True
>>> type(todos)

>>> todos[:10]
...

Ich würde dich nicht anlügen, aber ich bin froh, dass du ein Skeptiker bist.

What’s interactive mode? Ah, ich dachte du würdest nie fragen! Sie wissen, wie Sie immer zwischen Ihrem Editor und dem Terminal hin und her springen? Nun, wir hinterhältigen Pythoneer verwenden das interaktive Flag von-i, wenn wir das Skript ausführen. Dies ist ein großartiger kleiner Trick zum Testen von Code, da das Skript ausgeführt wird und dann eine interaktive Eingabeaufforderung mit Zugriff auf alle Daten aus dem Skript geöffnet wird!

Also gut, Zeit für etwas Action. Sie können die Struktur der Daten sehen, indem Sieendpoint in einem Browser aufrufen. Hier ist ein Beispiel für TODO:

{
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
}

Es gibt mehrere Benutzer mit jeweils einem eindeutigenuserId, und jede Aufgabe verfügt über eine booleschecompleted-Eigenschaft. Können Sie feststellen, welche Benutzer die meisten Aufgaben erledigt haben?

# Map of userId to number of complete TODOs for that user
todos_by_user = {}

# Increment complete TODOs count for each user.
for todo in todos:
    if todo["completed"]:
        try:
            # Increment the existing user's count.
            todos_by_user[todo["userId"]] += 1
        except KeyError:
            # This user has not been seen. Set their count to 1.
            todos_by_user[todo["userId"]] = 1

# Create a sorted list of (userId, num_complete) pairs.
top_users = sorted(todos_by_user.items(),
                   key=lambda x: x[1], reverse=True)

# Get the maximum number of complete TODOs.
max_complete = top_users[0][1]

# Create a list of all users who have completed
# the maximum number of TODOs.
users = []
for user, num_complete in top_users:
    if num_complete < max_complete:
        break
    users.append(str(user))

max_users = " and ".join(users)

Ja, ja, Ihre Implementierung ist besser, aber der Punkt ist, dass Sie jetzt die JSON-Daten als normales Python-Objekt bearbeiten können!

Ich weiß nichts über Sie, aber wenn ich das Skript erneut interaktiv ausführe, erhalte ich die folgenden Ergebnisse:

>>>

>>> s = "s" if len(users) > 1 else ""
>>> print(f"user{s} {max_users} completed {max_complete} TODOs")
users 5 and 10 completed 12 TODOs

Das ist cool und alles, aber Sie sind hier, um mehr über JSON zu erfahren. Für Ihre letzte Aufgabe erstellen Sie eine JSON-Datei, die die TODOs voncompletedfür jeden Benutzer enthält, der die maximale Anzahl von TODOs abgeschlossen hat.

Sie müssen lediglichtodos filtern und die resultierende Liste in eine Datei schreiben. Aus Gründen der Originalität können Sie die Ausgabedateifiltered_data_file.json aufrufen. Es gibt viele Möglichkeiten, wie Sie dies erreichen können, aber hier ist eine:

# Define a function to filter out completed TODOs
# of users with max completed TODOS.
def keep(todo):
    is_complete = todo["completed"]
    has_max_count = str(todo["userId"]) in users
    return is_complete and has_max_count

# Write filtered TODOs to file.
with open("filtered_data_file.json", "w") as data_file:
    filtered_todos = list(filter(keep, todos))
    json.dump(filtered_todos, data_file, indent=2)

Perfekt, Sie haben alle Daten entfernt, die Sie nicht benötigen, und die guten Sachen in einer brandneuen Datei gespeichert! Führen Sie das Skript erneut aus und überprüfen Siefiltered_data_file.json, um zu überprüfen, ob alles funktioniert hat. Es befindet sich beim Ausführen im selben Verzeichnis wiescratch.py.

Jetzt, wo du es bis hierher geschafft hast, fühlst du dich wie ein ziemlich heißes Zeug, oder? Sei nicht übermütig: Demut ist eine Tugend. Ich bin jedoch geneigt, Ihnen zuzustimmen. Bisher war es ein reibungsloses Segeln, aber vielleicht möchten Sie die Luken für diese letzte Etappe der Reise schließen.

Benutzerdefinierte Python-Objekte codieren und decodieren

Was passiert, wenn wir versuchen, dieElf-Klasse aus der Dungeons & Dragons-App zu serialisieren, an der Sie arbeiten?

class Elf:
    def __init__(self, level, ability_scores=None):
        self.level = level
        self.ability_scores = {
            "str": 11, "dex": 12, "con": 10,
            "int": 16, "wis": 14, "cha": 13
        } if ability_scores is None else ability_scores
        self.hp = 10 + self.ability_scores["con"]

Es überrascht nicht, dass Python sich darüber beschwert, dassElf nichtserializable ist (was Sie wissen würden, wenn Sie jemals versucht hätten, einem Elfen etwas anderes zu sagen):

>>>

>>> elf = Elf(level=4)
>>> json.dumps(elf)
TypeError: Object of type 'Elf' is not JSON serializable

Obwohl dasjson-Modul die meisten integrierten Python-Typen verarbeiten kann, versteht es nicht, wie benutzerdefinierte Datentypen standardmäßig codiert werden. Es ist, als würde man versuchen, einen quadratischen Stift in ein rundes Loch zu stecken - Sie benötigen eine Kreissäge und die Aufsicht der Eltern.

Datenstrukturen vereinfachen

Die Frage ist nun, wie mit komplexeren Datenstrukturen umgegangen werden soll. Sie könnten versuchen, JSON von Hand zu codieren und zu decodieren, aber es gibt eine etwas cleverere Lösung, die Ihnen Arbeit erspart. Anstatt direkt vom benutzerdefinierten Datentyp zu JSON zu wechseln, können Sie einen Zwischenschritt ausführen.

Alles, was Sie tun müssen, ist, Ihre Daten in Bezug auf die integrierten Typen darzustellen, diejson bereits versteht. Im Wesentlichen übersetzen Sie das komplexere Objekt in eine einfachere Darstellung, die dasjson-Modul dann in JSON übersetzt. Es ist wie die transitive Eigenschaft in der Mathematik: Wenn A = B und B = C, dann ist A = C.

Um den Dreh raus zu bekommen, benötigen Sie ein komplexes Objekt, mit dem Sie spielen können. Sie können jede beliebige benutzerdefinierte Klasse verwenden, aber Python verfügt über einen integrierten Typ namenscomplex zur Darstellung komplexer Zahlen und ist standardmäßig nicht serialisierbar. Aus Gründen dieser Beispiele wird Ihr komplexes Objekt eincomplex-Objekt sein. Noch verwirrt?

>>>

>>> z = 3 + 8j
>>> type(z)

>>> json.dumps(z)
TypeError: Object of type 'complex' is not JSON serializable

Where do complex numbers come from? Wenn sich eine reelle Zahl und eine imaginäre Zahl sehr lieben, addieren sie sich zu einer Zahl, die (zu Recht)complex heißt.

Eine gute Frage, die Sie sich bei der Arbeit mit benutzerdefinierten Typen stellen sollten, istWhat is the minimum amount of information necessary to recreate this object?. Bei komplexen Zahlen müssen Sie nur den Real- und Imaginärteil kennen, auf die Sie beide als Attribute fürcomplex zugreifen können Objekt:

>>>

>>> z.real
3.0
>>> z.imag
8.0

Die Übergabe derselben Zahlen an einencomplex-Konstruktor reicht aus, um den Vergleichsoperator von__eq__zu erfüllen:

>>>

>>> complex(3, 8) == z
True

Die Aufteilung benutzerdefinierter Datentypen in ihre wesentlichen Komponenten ist sowohl für den Serialisierungs- als auch für den Deserialisierungsprozess von entscheidender Bedeutung.

Benutzerdefinierte Typen codieren

Um ein benutzerdefiniertes Objekt in JSON zu übersetzen, müssen Sie lediglich eine Codierungsfunktion für dendefault-Parameter derdump()-Methode bereitstellen. Das%(t2)s Modul wird diese Funktion für alle Objekte aufrufen, die nicht nativ Serialisierbar sind. Hier ist eine einfache Dekodierungsfunktion, die Sie zum Üben verwenden können:

def encode_complex(z):
    if isinstance(z, complex):
        return (z.real, z.imag)
    else:
        type_name = z.__class__.__name__
        raise TypeError(f"Object of type '{type_name}' is not JSON serializable")

Beachten Sie, dass Sie voraussichtlich einenTypeError erhöhen, wenn Sie nicht die Art von Objekt erhalten, die Sie erwartet haben. Auf diese Weise vermeiden Sie, dass Elfen versehentlich serialisiert werden. Jetzt können Sie versuchen, komplexe Objekte selbst zu codieren!

>>>

>>> json.dumps(9 + 5j, default=encode_complex)
'[9.0, 5.0]'
>>> json.dumps(elf, default=encode_complex)
TypeError: Object of type 'Elf' is not JSON serializable

Why did we encode the complex number as a tuple? Gute Frage! Das war sicherlich nicht die einzige Wahl, und es ist auch nicht unbedingt die beste Wahl. Tatsächlich wäre dies keine sehr gute Darstellung, wenn Sie das Objekt später entschlüsseln wollten, wie Sie gleich sehen werden.

Der andere übliche Ansatz besteht darin, den StandardJSONEncoder zu unterklassifizieren und seinedefault()-Methode zu überschreiben:

class ComplexEncoder(json.JSONEncoder):
    def default(self, z):
        if isinstance(z, complex):
            return (z.real, z.imag)
        else:
            return super().default(z)

Anstatt dieTypeError selbst zu erhöhen, können Sie einfach die Basisklasse damit umgehen lassen. Sie können dies entweder direkt in derdump()-Methode über dencls-Parameter verwenden oder indem Sie eine Instanz des Encoders erstellen und dessenencode()-Methode aufrufen:

>>>

>>> json.dumps(2 + 5j, cls=ComplexEncoder)
'[2.0, 5.0]'

>>> encoder = ComplexEncoder()
>>> encoder.encode(3 + 6j)
'[3.0, 6.0]'

Benutzerdefinierte Typen dekodieren

Während die Real- und Imaginärteile einer komplexen Zahl absolut notwendig sind, reichen sie tatsächlich nicht aus, um das Objekt neu zu erstellen. Dies passiert, wenn Sie versuchen, eine komplexe Zahl mitComplexEncoder zu codieren und dann das Ergebnis zu decodieren:

>>>

>>> complex_json = json.dumps(4 + 17j, cls=ComplexEncoder)
>>> json.loads(complex_json)
[4.0, 17.0]

Sie erhalten lediglich eine Liste und müssen die Werte an den Konstruktorcomplexübergeben, wenn Sie das komplexe Objekt erneut möchten. Erinnern Sie sich an unsere Diskussion überteleportation. Was fehlt, sindmetadata oder Informationen über den Datentyp, den Sie codieren.

Ich nehme an, die Frage, die Sie sich wirklich stellen sollten, istWhat is the minimum amount of information that is both necessary and sufficient to recreate this object?

Das Moduljson erwartet, dass alle benutzerdefinierten Typen im JSON-Standard alsobjects ausgedrückt werden. Aus Gründen der Abwechslung können Sie diesmal eine JSON-Datei mit dem Namencomplex_data.json erstellen und die folgendenobject hinzufügen, die eine komplexe Zahl darstellen:

{
    "__complex__": true,
    "real": 42,
    "imag": 36
}

Sehen Sie das kluge Stück? Der"__complex__"-Schlüssel sind die Metadaten, über die wir gerade gesprochen haben. Es spielt keine Rolle, um welchen Wert es sich handelt. Damit dieser kleine Hack funktioniert, müssen Sie lediglich überprüfen, ob der Schlüssel vorhanden ist:

def decode_complex(dct):
    if "__complex__" in dct:
        return complex(dct["real"], dct["imag"])
    return dct

Wenn"__complex__" nicht im Wörterbuch enthalten ist, können Sie das Objekt einfach zurückgeben und den Standarddecoder damit beauftragen.

Jedes Mal, wenn die Methodeload()versucht,objectzu analysieren, haben Sie die Möglichkeit, einzugreifen, bevor der Standarddecoder die Daten verarbeitet. Sie können dies tun, indem Sie Ihre Dekodierungsfunktion an den Parameterobject_hookübergeben.

Spielen Sie jetzt die gleiche Art von Spiel wie zuvor:

>>>

>>> with open("complex_data.json") as complex_data:
...     data = complex_data.read()
...     z = json.loads(data, object_hook=decode_complex)
...
>>> type(z)

Während sichobject_hook wie das Gegenstück zumdefault-Parameter derdump()-Methode anfühlt, beginnt und endet die Analogie wirklich dort.

Dies funktioniert auch nicht nur mit einem Objekt. Versuchen Sie, diese Liste komplexer Zahlen incomplex_data.json einzufügen und das Skript erneut auszuführen:

[
  {
    "__complex__":true,
    "real":42,
    "imag":36
  },
  {
    "__complex__":true,
    "real":64,
    "imag":11
  }
]

Wenn alles gut geht, erhalten Sie eine Liste der Objekte voncomplex:

>>>

>>> with open("complex_data.json") as complex_data:
...     data = complex_data.read()
...     numbers = json.loads(data, object_hook=decode_complex)
...
>>> numbers
[(42+36j), (64+11j)]

Sie können auch versuchen,JSONDecoder in Unterklassen zu unterteilen undobject_hook zu überschreiben. Es ist jedoch besser, wenn möglich bei der Lightweight-Lösung zu bleiben.

Alles erledigt!

Herzlichen Glückwunsch, Sie können jetzt die mächtige Kraft von JSON für alle Python-Anforderungen vonnefariousnutzen.

Die Beispiele, mit denen Sie hier gearbeitet haben, sind sicherlich erfunden und zu simpel. Sie veranschaulichen jedoch einen Workflow, den Sie auf allgemeinere Aufgaben anwenden können:

  1. Importieren Sie das Paketjson.

  2. Lesen Sie die Daten mitload() oderloads().

  3. Verarbeiten Sie die Daten.

  4. Schreiben Sie die geänderten Daten mitdump() oderdumps().

Was Sie mit Ihren Daten tun, nachdem sie in den Speicher geladen wurden, hängt von Ihrem Anwendungsfall ab. Im Allgemeinen besteht Ihr Ziel darin, Daten aus einer Quelle zu sammeln, nützliche Informationen zu extrahieren und diese Informationen weiterzugeben oder aufzuzeichnen.

Heute haben Sie eine Reise unternommen: Sie haben einige wilde JSON gefangen genommen und gezähmt, und Sie haben es rechtzeitig zum Abendessen zurück geschafft! Als zusätzlichen Bonus macht das Lernen desjson-Pakets das Lernen vonpickle undmarshal zum Kinderspiel.

Viel Glück bei all deinen zukünftigen pythonischen Bemühungen!