Dieser Leitfaden behandelt das Parsen von JSON-Daten mit dem json-Modul in Python sowie deren Umwandlung in ein Python-Dictionary und umgekehrt.
- Eine Einführung in JSON in Python
- JSON-Daten mit Python parsen
- Einen JSON-String in ein Python-Dictionary konvertieren
- Python-Daten in JSON konvertieren
- Einschränkungen des
json-Standardmoduls - Fazit
JavaScript Object Notation, oder JSON, ist ein leichtgewichtiges Datenaustauschformat, das häufig zur Übertragung von Daten zwischen Servern und Webanwendungen über APIs verwendet wird. JSON-Daten bestehen aus Schlüssel-Wert-Paaren, wobei jeder Schlüssel ein String ist und jeder Wert ein String, eine Zahl, ein Boolean, null, ein Array oder ein Objekt sein kann.
Hier ist ein Beispiel für JSON:
{
"name": "Maria Smith",
"age": 32,
"isMarried": true,
"hobbies": ["reading", "jogging"],
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "12345"
},
"phoneNumbers": [
{
"type": "home",
"number": "555-555-1234"
},
{
"type": "work",
"number": "555-555-5678"
}
],
"notes": null
}Python unterstützt nativ JSON über das json-Modul, das Teil der Python Standard Library ist. Das bedeutet, dass Sie keine zusätzliche Library installieren müssen, um mit JSON in Python zu arbeiten. Sie können json wie folgt importieren:
import jsonDie integrierte Python-json-Library stellt eine vollständige API bereit, um mit JSON zu arbeiten. Insbesondere hat sie zwei zentrale Funktionen: loads und load. Die Funktion loads dient zum Parsen von JSON-Daten aus einem String, während die Funktion load zum Parsen von JSON-Daten in Bytes dient.
Über diese beiden Methoden ermöglicht json, JSON-Daten in äquivalente Python-Objekte wie Dictionaries und Listen zu konvertieren und umgekehrt. Außerdem ermöglicht das json-Modul, benutzerdefinierte Encoder und Decoder zu erstellen, um spezifische Datentypen zu behandeln.
Angenommen, Sie haben einige JSON-Daten in einem String gespeichert und möchten diese in ein Python-Dictionary konvertieren. So sehen die JSON-Daten aus:
{
"name": "iPear 23",
"colors": ["black", "white", "red", "blue"],
"price": 999.99,
"inStock": true
}Und dies ist die String-Repräsentation in Python:
smartphone_json = '{"name": "iPear 23", "colors": ["black", "white", "red", "blue"], "price": 999.99, "inStock": true}'Hinweis
Erwägen Sie, die Python-Konvention mit dreifachen Anführungszeichen zu verwenden, um lange mehrzeilige JSON-Strings zu speichern.
Sie können mit der folgenden Zeile überprüfen, dass smartphone einen gültigen Python-String enthält:
print(type(smartphone))Dies wird ausgeben:
<class 'str'>
str steht für „String“ und bedeutet, dass die Variable smartphone den Typ Textsequenz hat.
Parsen Sie den in smartphone enthaltenen JSON-String mit der Methode json.loads() wie folgt in ein Python-Dictionary:
import json
# JSON string
smartphone_json = '{"name": "iPear 23", "colors": ["black", "white", "red", "blue"], "price": 999.99, "inStock": true}'
# from JSON string to Python dict
smartphone_dict = json.loads(smartphone_json)
# verify the type of the resulting variable
print(type(smartphone_dict)) # dictWenn Sie dieses Snippet ausführen, erhalten Sie:
<class 'dict'>
Nun enthält smartphone_dict ein gültiges Python-Dictionary.
Als Nächstes übergeben Sie einen gültigen JSON-String an json.loads(), um einen JSON-String in ein Python-Dictionary zu konvertieren.
Sie können nun wie gewohnt auf die Felder des resultierenden Dictionaries zugreifen:
product = smartphone_dict['name'] # smartphone
priced = smartphone['price'] # 999.99
colors = smartphone['colors'] # ['black', 'white', 'red', 'blue']Die Funktion json.loads() gibt nicht immer ein Dictionary zurück. Insbesondere hängt der Rückgabedatentyp vom Eingabestring ab. Wenn der JSON-String beispielsweise einen flachen Wert enthält, wird er in den entsprechenden Python-Primitive-Wert konvertiert:
import json
json_string = '15.5'
float_var = json.loads(json_string)
print(type(float_var)) # <class 'float'>Ebenso wird ein JSON-String, der eine Array-Liste enthält, zu einer Python-Liste:
import json
json_string = '[1, 2, 3]'
list_var = json.loads(json_string)
print(json_string) # <class 'list'>Die folgende Konvertierungstabelle erklärt, wie JSON-Werte durch json in Python-Daten konvertiert werden:
| JSON Value | Python Data |
| - | - | - |
| string | str |
| number (integer) | int |
| number (real) | float |
| true | True |
| false | False |
| null | None |
| array | list |
| object | dict |
Angenommen, Sie müssen eine API aufrufen und deren JSON-Antwort in ein Python-Dictionary konvertieren. Im folgenden Beispiel rufen wir den folgenden API-Endpunkt aus dem Projekt {JSON} Placeholder auf, um einige Fake-JSON-Daten zu erhalten:
https://jsonplaceholder.typicode.com/todos/1
Diese RESTFul API liefert die folgende JSON-Antwort zurück:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}Sie können diese API mit dem Modul urllib aus der Standard Library aufrufen und das resultierende JSON wie folgt in ein Python-Dictionary konvertieren:
import urllib.request
import json
url = "https://jsonplaceholder.typicode.com/todos/1"
with urllib.request.urlopen(url) as response:
body_json = response.read()
body_dict = json.loads(body_json)
user_id = body_dict['userId'] # 1urllib.request.urlopen() führt den API-Aufruf aus und gibt ein HTTPResponse-Objekt zurück. Dessen Methode read() wird dann verwendet, um den Response-Body body_json zu erhalten, der die API-Antwort als JSON-String enthält. Schließlich kann dieser String wie zuvor erläutert über json.loads() in ein Python-Dictionary geparst werden.
Ebenso können Sie dasselbe Ergebnis mit requests: erzielen.
import requests
import json
url = "https://jsonplaceholder.typicode.com/todos/1"
response = requests.get(url)
body_dict = response.json()
user_id = body_dict['userId'] # 1Hinweis
Die Methode.json()transformiert das Response-Objekt mit JSON-Daten automatisch in die entsprechende Python-Datenstruktur.
Angenommen, Sie haben einige JSON-Daten in einer Datei smartphone.json gespeichert, wie unten dargestellt:
{
"name": "iPear 23",
"colors": ["black", "white", "red", "blue"],
"price": 999.99,
"inStock": true,
"dimensions": {
"width": 2.82,
"height": 5.78,
"depth": 0.30
},
"features": [
"5G",
"HD display",
"Dual camera"
]
}Ihr Ziel ist es, die JSON-Datei zu lesen und in ein Python-Dictionary zu laden. Erreichen Sie dies mit dem folgenden Snippet:
import json
with open('smartphone.json') as file:
smartphone_dict = json.load(file)
print(type(smartphone_dict)) # <class 'dict'>
features = smartphone_dict['features'] # ['5G', 'HD display', 'Dual camera']Die integrierte Library open() ermöglicht es Ihnen, eine Datei zu laden und das entsprechende file object zu erhalten. Die Methode json.read() deserialisiert dann die text file oder binary file, die ein JSON-Dokument enthält, in das äquivalente Python-Objekt. In diesem Fall wird smartphone.json zu einem Python-Dictionary.
Nun parsen wir einige JSON-Daten in eine benutzerdefinierte Python-Klasse. So sieht Ihre benutzerdefinierte Smartphone-Python-Klasse aus:
class Smartphone:
def __init__(self, name, colors, price, in_stock):
self.name = name
self.colors = colors
self.price = price
self.in_stock = in_stockHier besteht das Ziel darin, den folgenden JSON-String in eine Smartphone-Instanz zu konvertieren:
{
"name": "iPear 23 Plus",
"colors": ["black", "white", "gold"],
"price": 1299.99,
"inStock": false
}Erstellen Sie einen benutzerdefinierten Decoder, um diese Aufgabe zu erfüllen. Erweitern Sie dazu die Klasse JSONDecoder und setzen Sie den Parameter object_hook in der __init__-Methode. Weisen Sie ihm den Namen der Klassenmethode zu, die die benutzerdefinierte Parsing-Logik enthält. In dieser Parsing-Methode können Sie die Werte verwenden, die im Standard-Dictionary enthalten sind, das von json.read() zurückgegeben wird, um ein Smartphone-Objekt zu instanziieren.
Definieren Sie einen benutzerdefinierten SmartphoneDecoder wie folgt:
import json
class SmartphoneDecoder(json.JSONDecoder):
def __init__(self, object_hook=None, *args, **kwargs):
# set the custom object_hook method
super().__init__(object_hook=self.object_hook, *args, **kwargs)
# class method containing the
# custom parsing logic
def object_hook(self, json_dict):
new_smartphone = Smartphone(
json_dict.get('name'),
json_dict.get('colors'),
json_dict.get('price'),
json_dict.get('inStock'),
)
return new_smartphoneVerwenden Sie die Methode get(), um die Dictionary-Werte innerhalb der benutzerdefinierten Methode object_hook() zu lesen. Dadurch wird sichergestellt, dass keine KeyErrors ausgelöst werden, falls ein Schlüssel im Dictionary fehlt. Stattdessen werden None-Werte zurückgegeben.
Übergeben Sie nun die Klasse SmartphoneDecoder an den Parameter cls in json.loads(), um einen JSON-String in ein Smartphone-Objekt zu konvertieren:
import json
# class Smartphone:
# ...
# class SmartphoneDecoder(json.JSONDecoder):
# ...
smartphone_json = '{"name": "iPear 23 Plus", "colors": ["black", "white", "gold"], "price": 1299.99, "inStock": false}'
smartphone = json.loads(smartphone_json, cls=SmartphoneDecoder)
print(type(smartphone)) # <class '__main__.Smartphone'>
name = smartphone.name # iPear 23 PlusAnalog können Sie SmartphoneDecoder auch mit json.load() verwenden:
smartphone = json.load(smartphone_json_file, cls=SmartphoneDecoder)
Sie können auch in die andere Richtung gehen und Python-Datenstrukturen sowie Primitive in JSON konvertieren. Dies ist dank der Funktionen json.dump() und json.dumps() möglich, die der folgenden Konvertierungstabelle folgen:
| Python Data | JSON Value |
| - | - | - |
| str | string |
| int | number (integer) |
| float | number (real) |
| True | true |
| False | false |
| None | null |
| list | array |
| dict | object |
| Null | None |
json.dump() ermöglicht es Ihnen, einen JSON-String in eine Datei zu schreiben, wie im folgenden Beispiel:
import json
user_dict = {
"name": "John",
"surname": "Williams",
"age": 48,
"city": "New York"
}
# serializing the sample dictionary to a JSON file
with open("user.json", "w") as json_file:
json.dump(user_dict, json_file)Dieses Snippet serialisiert die Python-Variable user_dict in die Datei user.json.
Ebenso konvertiert json.dumps() eine Python-Variable in den entsprechenden JSON-String:
import json
user_dict = {
"name": "John",
"surname": "Williams",
"age": 48,
"city": "New York"
}
user_json_string = json.dumps(user_dict)
print(user_json_string)Führen Sie dieses Snippet aus und Sie erhalten:
{"name": "John", "surname": "Williams", "age": 48, "city": "New York"}Hinweis
Folgen Sie der offiziellen Dokumentation, um zu erfahren, wie Sie einen benutzerdefinierten Encoder angeben.
Das Parsen von Daten aus JSON bringt Herausforderungen mit sich, die nicht übersehen werden dürfen.
Zwei häufige Beispiele sind:
- Das Python-
json-Modul reicht nicht aus bei ungültigem, beschädigtem oder nicht standardkonformem JSON. - Das Parsen von JSON-Daten aus nicht vertrauenswürdigen Quellen ist gefährlich, da ein bösartiger JSON-String dazu führen kann, dass Ihr Parser ausfällt oder eine große Menge an Ressourcen verbraucht.
Diese Einschränkungen können umgangen werden, aber am besten verwenden Sie ein kommerzielles Tool, das das JSON-Parsen erleichtert, wie z. B. Web Scraper API.
Beim nativen Parsen von JSON-Daten über das json-Standardmodul in Python benötigen Sie zuverlässige Proxy-Server, um von Websites auferlegte Einschränkungen zu umgehen. Testen Sie eine hochmoderne, voll ausgestattete, kommerzielle Lösung für das Parsen von Daten, wie z. B. die Daten- und Proxy products von Bright Data.
