Python Language
Moduł JSON
Szukaj…
Uwagi
Pełna dokumentacja, w tym funkcje specyficzne dla wersji, znajduje się w oficjalnej dokumentacji .
Rodzaje
Domyślne
moduł json
domyślnie obsługuje kodowanie i dekodowanie poniższych typów:
Typy usuwania serializacji:
JSON | Pyton |
---|---|
obiekt | dyktować |
szyk | lista |
strunowy | str |
liczba (int) | int |
liczba (rzeczywista) | pływak |
prawda fałsz | Prawda fałsz |
zero | Żaden |
Moduł json
również rozumie NaN
, Infinity
i -Infinity
jako odpowiadające im wartości zmiennoprzecinkowe, które są poza specyfikacją JSON.
Typy serializacji:
Pyton | JSON |
---|---|
dyktować | obiekt |
lista, krotka | szyk |
str | strunowy |
int, float, (int / float) wyprowadzone Enums | numer |
Prawdziwe | prawdziwe |
Fałszywy | fałszywy |
Żaden | zero |
Aby zabronić kodowania NaN
, Infinity
i -Infinity
, musisz zakodować za pomocą allow_nan=False
. Spowoduje to podniesienie ValueError
jeśli spróbujesz zakodować te wartości.
Niestandardowa (de-) serializacja
Istnieją różne haki, które pozwalają przetwarzać dane, które muszą być reprezentowane w różny sposób. Zastosowanie functools.partial
pozwala częściowo zastosować odpowiednie parametry do tych funkcji dla wygody.
Serializacja:
Możesz podać funkcję, która działa na obiektach przed ich serializacją w następujący sposób:
# my_json module
import json
from functools import partial
def serialise_object(obj):
# Do something to produce json-serialisable data
return dict_obj
dump = partial(json.dump, default=serialise_object)
dumps = partial(json.dumps, default=serialise_object)
Dezeralizacja:
Istnieją różne haki obsługiwane przez funkcje json, takie jak object_hook i parse_float. Wyczerpująca lista twojej wersji Pythona znajduje się tutaj .
# my_json module
import json
from functools import partial
def deserialise_object(dict_obj):
# Do something custom
return obj
def deserialise_float(str_obj):
# Do something custom
return obj
load = partial(json.load, object_hook=deserialise_object, parse_float=deserialise_float)
loads = partial(json.loads, object_hook=deserialise_object, parse_float=deserialise_float)
Dalsza niestandardowa (de-) serializacja:
Moduł json
pozwala również na rozszerzenie / podstawienie json.JSONEncoder
i json.JSONDecoder
do obsługi różnych typów. Haki udokumentowane powyżej można dodać jako domyślne, tworząc metodę o równoważnej nazwie. Aby ich użyć, wystarczy przekazać klasę jako parametr cls
do odpowiedniej funkcji. Zastosowanie functools.partial
pozwala częściowo zastosować parametr cls do tych funkcji dla wygody, np
# my_json module
import json
from functools import partial
class MyEncoder(json.JSONEncoder):
# Do something custom
class MyDecoder(json.JSONDecoder):
# Do something custom
dump = partial(json.dump, cls=MyEncoder)
dumps = partial(json.dumps, cls=MyEncoder)
load = partial(json.load, cls=MyDecoder)
loads = partial(json.loads, cls=MyDecoder)
Tworzenie JSON z Python Dict
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
Powyższy fragment kodu zwróci następujące informacje:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
Tworzenie słownika Python z JSON
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
Powyższy fragment kodu zwróci następujące informacje:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
Przechowywanie danych w pliku
Poniższy fragment kodu koduje dane zapisane w d
do JSON i zapisuje je w pliku (zamień filename
na rzeczywistą nazwę pliku).
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(filename, 'w') as f:
json.dump(d, f)
Pobieranie danych z pliku
Poniższy fragment kodu otwiera plik zakodowany w JSON (zamień filename
na rzeczywistą nazwę pliku) i zwraca obiekt przechowywany w pliku.
import json
with open(filename, 'r') as f:
d = json.load(f)
„ładuj” vs „ładunki”, „zrzut” vs „zrzuty”
Moduł json
zawiera funkcje zarówno do odczytu i zapisu do i z ciągów znaków Unicode oraz do odczytu i zapisu do i z plików. Różnią się one znakiem końcowym s
w nazwie funkcji. W tych przykładach używamy obiektu StringIO, ale te same funkcje miałyby zastosowanie do każdego obiektu podobnego do pliku.
Tutaj używamy funkcji opartych na łańcuchach:
import json
data = {u"foo": u"bar", u"baz": []}
json_string = json.dumps(data)
# u'{"foo": "bar", "baz": []}'
json.loads(json_string)
# {u"foo": u"bar", u"baz": []}
I tutaj korzystamy z funkcji opartych na plikach:
import json
from io import StringIO
json_file = StringIO()
data = {u"foo": u"bar", u"baz": []}
json.dump(data, json_file)
json_file.seek(0) # Seek back to the start of the file before reading
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
json_file.seek(0) # Seek back to the start of the file before reading
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Jak widać, główna różnica polega na tym, że podczas zrzutu danych JSON należy przekazać uchwyt pliku do funkcji, w przeciwieństwie do przechwytywania wartości zwracanej. Warto również zauważyć, że należy szukać początku pliku przed odczytem lub zapisem, aby uniknąć uszkodzenia danych. Podczas otwierania pliku kursor jest umieszczany w pozycji 0
, więc działałoby również:
import json
json_file_path = './data.json'
data = {u"foo": u"bar", u"baz": []}
with open(json_file_path, 'w') as json_file:
json.dump(data, json_file)
with open(json_file_path) as json_file:
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
with open(json_file_path) as json_file:
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Oba sposoby postępowania z danymi json pozwalają na idiomatyczną i wydajną pracę z formatami pyspark
na json, takimi jak json-per-line w pyspark
:
# loading from a file
data = [json.loads(line) for line in open(file_path).splitlines()]
# dumping to a file
with open(file_path, 'w') as json_file:
for item in data:
json.dump(item, json_file)
json_file.write('\n')
Wywołanie `json.tool` z wiersza poleceń w celu wydrukowania ładnego wyniku JSON
Biorąc pod uwagę plik JSON „foo.json”, taki jak:
{"foo": {"bar": {"baz": 1}}}
możemy wywołać moduł bezpośrednio z linii poleceń (przekazując nazwę pliku jako argument), aby go ładnie wydrukować:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
Moduł pobierze również dane wejściowe z STDOUT, więc (w Bash) możemy równie dobrze zrobić:
$ cat foo.json | python -m json.tool
Formatowanie wyjścia JSON
Powiedzmy, że mamy następujące dane:
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Po prostu zrzucam to, ponieważ JSON nie robi tutaj nic specjalnego:
>>> print(json.dumps(data))
{"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Ustawienie wcięcia, aby uzyskać ładniejszy wynik
Jeśli chcemy ładnego drukowania, możemy ustawić indent
:
>>> print(json.dumps(data, indent=2))
{
"cats": [
{
"name": "Tubbs",
"color": "white"
},
{
"name": "Pepper",
"color": "black"
}
]
}
Sortuj klucze alfabetycznie, aby uzyskać spójny wynik
Domyślnie kolejność kluczy w danych wyjściowych jest niezdefiniowana. Możemy uzyskać je w kolejności alfabetycznej, aby mieć pewność, że zawsze otrzymamy ten sam wynik:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
Pozbycie się białych znaków, aby uzyskać kompaktowe wyjście
Możemy chcieć pozbyć się niepotrzebnych spacji, co odbywa się poprzez ustawienie ciągów separatora innych niż domyślne ', '
i ': '
:
>>>print(json.dumps(data, separators=(',', ':')))
{"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
Kodowanie niestandardowych obiektów JSON
Jeśli po prostu spróbujemy:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
się błąd informujący, że TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
.
Aby móc poprawnie serializować obiekt datetime, musimy napisać niestandardowy kod, aby go przekonwertować:
class DatetimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
try:
return obj.isoformat()
except AttributeError:
# obj has no isoformat method; let the builtin JSON encoder handle it
return super(DatetimeJSONEncoder, self).default(obj)
a następnie użyj tej klasy kodera zamiast json.dumps
:
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}