Python Language
JSON-modul
Sök…
Anmärkningar
Kontrollera den officiella dokumentationen för full dokumentation inklusive versionspecifik funktionalitet.
typer
defaults
json
modulen hanterar kodning och avkodning av nedanstående typer som standard:
Avserialiseringstyper:
JSON | Pytonorm |
---|---|
objekt | dict |
array | lista |
sträng | str |
nummer (int) | int |
nummer (verkligt) | flyta |
sant falskt | Sant falskt |
null | Ingen |
json
modulen förstår också NaN
, Infinity
och -Infinity
som deras motsvarande flottörvärden, som ligger utanför JSON-specifikationen.
Serialiseringstyper:
Pytonorm | JSON |
---|---|
dict | objekt |
lista, tupel | array |
str | sträng |
int, float, (int / float) -ledda Enums | siffra |
Sann | Sann |
Falsk | falsk |
Ingen | null |
För att tillåta kodning av NaN
, Infinity
och- -Infinity
måste du koda med allow_nan=False
. Detta höjer sedan en ValueError
om du försöker att koda dessa värden.
Anpassad (de-) serialisering
Det finns olika krokar som gör att du kan hantera data som måste representeras annorlunda. Användning av functools.partial
låter dig delvis tillämpa relevanta parametrar på dessa funktioner för bekvämlighet.
Serialization:
Du kan tillhandahålla en funktion som fungerar på objekt innan de seriellt görs så:
# 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)
De-serie:
Det finns olika krokar som hanteras av json-funktionerna, till exempel object_hook och parse_float. För en uttömmande lista för din version av python, se här .
# 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)
Ytterligare anpassad (de-) serialisering:
json
modulen tillåter också förlängning / utbyte av json.JSONEncoder
och json.JSONDecoder
att hantera diverse typer. Krokarna som dokumenterats ovan kan läggas till som standard genom att skapa en likvärdigt benämnd metod. För att använda dessa, skicka bara klassen som cls
parameter till relevant funktion. Användning av functools.partial
låter dig delvis tillämpa cls-parametern på dessa funktioner för bekvämlighet, t.ex.
# 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)
Skapa JSON från Python dict
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
Ovanstående kod kommer att returnera följande:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
Skapa Python dict från JSON
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
Ovanstående kod kommer att returnera följande:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
Lagring av data i en fil
Följande kod kodar data lagrade i d
i JSON och lagrar dem i en fil (ersätt filename
med filens faktiska namn).
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(filename, 'w') as f:
json.dump(d, f)
Hämtar data från en fil
Följande kodavsnitt öppnar en JSON-kodad fil (ersätt filename
med filens verkliga namn) och returnerar objektet som är lagrat i filen.
import json
with open(filename, 'r') as f:
d = json.load(f)
`last` vs` loads`, `dump` vs` dumps`
json
modulen innehåller funktioner för både läsning och skrivning till och från unicode-strängar, och läsning och skrivning till och från filer. Dessa skiljer sig genom en avslutande s
i funktionsnamnet. I dessa exempel använder vi ett StringIO-objekt, men samma funktioner skulle gälla för alla filliknande objekt.
Här använder vi de strängbaserade funktionerna:
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": []}
Och här använder vi de filbaserade funktionerna:
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": []}
Som du kan se är huvudskillnaden att när du dumpar json-data måste du skicka filhandtaget till funktionen, i motsats till att fånga returvärdet. Det är också värt att notera att du måste försöka börja filen innan du läser eller skriver för att undvika datakorruption. När du öppnar en fil placeras markören på position 0
, så nedan fungerar också:
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": []}
Genom att ha båda sätten att hantera json-data kan du idiomatiskt och effektivt arbeta med format som bygger på json, till exempel pyspark
's json-per-line:
# 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')
Ringa `json.tool` från kommandoraden för att skriva ut JSON-utgången
Får en del JSON-fil "foo.json" som:
{"foo": {"bar": {"baz": 1}}}
vi kan ringa modulen direkt från kommandoraden (passera filnamnet som ett argument) för att skriva ut den:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
Modulen tar också input från STDOUT, så (i Bash) kan vi lika göra:
$ cat foo.json | python -m json.tool
Formatera JSON-utgången
Låt oss säga att vi har följande data:
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Bara dumpa detta eftersom JSON inte gör något speciellt här:
>>> print(json.dumps(data))
{"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Ställer in intryck för att få snyggare utdata
Om vi vill ha bra utskrift kan vi ställa in en indent
:
>>> print(json.dumps(data, indent=2))
{
"cats": [
{
"name": "Tubbs",
"color": "white"
},
{
"name": "Pepper",
"color": "black"
}
]
}
Sortera tangenter alfabetiskt för att få konsekvent utdata
Som standard är knapparnas ordning inte definierad. Vi kan få dem i alfabetisk ordning för att se till att vi alltid får samma output:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
Bli av med utrymme för att få kompakt utgång
Vi kanske vill bli av med onödiga utrymmen, vilket görs genom att ställa in separatorsträngar som skiljer sig från standard ', '
och ': '
:
>>>print(json.dumps(data, separators=(',', ':')))
{"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
JSON som kodar anpassade objekt
Om vi bara försöker följande:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
vi får ett fel med att säga TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
.
För att kunna serialisera datetime-objektet ordentligt måste vi skriva anpassad kod för hur man konverterar det:
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)
och använd sedan denna kodare i stället för json.dumps
:
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}