Python Language
Modulo JSON
Ricerca…
Osservazioni
Per la documentazione completa inclusa la funzionalità specifica della versione, consultare la documentazione ufficiale .
tipi
Defaults
il modulo json
gestirà la codifica e la decodifica dei seguenti tipi di default:
Tipi di serializzazione:
JSON | Pitone |
---|---|
oggetto | dict |
schieramento | elenco |
stringa | str |
numero (int) | int |
numero (reale) | galleggiante |
vero falso | Vero falso |
nullo | Nessuna |
Il modulo json
comprende anche NaN
, Infinity
e -Infinity
come valori float corrispondenti, che è al di fuori della specifica JSON.
Tipi di serializzazione:
Pitone | JSON |
---|---|
dict | oggetto |
lista, tupla | schieramento |
str | stringa |
int, float, (int / float) -derived Enums | numero |
Vero | vero |
falso | falso |
Nessuna | nullo |
Per disabilitare la codifica di NaN
, Infinity
e -Infinity
devi codificare con allow_nan=False
. Ciò solleverà ValueError
se ValueError
di codificare questi valori.
Serializzazione personalizzata (de-)
Esistono vari hook che consentono di gestire i dati che devono essere rappresentati in modo diverso. L'uso di functools.partial
consente di applicare parzialmente i parametri rilevanti a queste funzioni per comodità.
serializzazione:
È possibile fornire una funzione che opera sugli oggetti prima di essere serializzati in questo modo:
# 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-serializzazione:
Ci sono vari hook che sono gestiti dalle funzioni JSON, come object_hook e parse_float. Per un elenco completo per la tua versione di Python, vedi qui .
# 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)
Ulteriori personalizzazioni (de-) serializzazione:
Il modulo json
consente anche l'estensione / sostituzione di json.JSONEncoder
e json.JSONDecoder
per gestire vari tipi. Gli hook documentati sopra possono essere aggiunti come predefiniti creando un metodo con un nome equivalente. Per utilizzarli basta passare la classe come parametro cls
alla funzione rilevante. L'uso di functools.partial
consente di applicare parzialmente il parametro cls a queste funzioni per comodità, ad es
# 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)
Creazione di JSON da Python dict
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
Lo snippet riportato sopra restituirà quanto segue:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
Creazione di Dict Python da JSON
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
Lo snippet riportato sopra restituirà quanto segue:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
Memorizzazione di dati in un file
Il seguente frammento codifica i dati memorizzati in d
in JSON e li archivia in un file (sostituisce il filename
con il nome effettivo del file).
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(filename, 'w') as f:
json.dump(d, f)
Recupero di dati da un file
Lo snippet seguente apre un file con codifica JSON (sostituisce il filename
con il nome effettivo del file) e restituisce l'oggetto che è archiviato nel file.
import json
with open(filename, 'r') as f:
d = json.load(f)
`load` vs` loads`, `dump` vs` dumps`
Il modulo json
contiene funzioni sia per la lettura e la scrittura da e verso le stringhe Unicode, sia per la lettura e la scrittura da e verso i file. Questi sono differenziati da un trailing s
nel nome della funzione. In questi esempi utilizziamo un oggetto StringIO, ma le stesse funzioni si applicherebbero a qualsiasi oggetto simile a un file.
Qui usiamo le funzioni basate su stringhe:
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": []}
E qui usiamo le funzioni basate su file:
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": []}
Come puoi vedere, la differenza principale è che quando si scaricano dati json è necessario passare l'handle del file alla funzione, invece di acquisire il valore restituito. Vale anche la pena notare che è necessario cercare all'inizio del file prima di leggere o scrivere, al fine di evitare la corruzione dei dati. Quando si apre un file, il cursore si trova nella posizione 0
, quindi anche il seguente funzionerà:
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": []}
Avere entrambi i modi di gestire i dati json consente di lavorare in modo idiomatico ed efficiente con i formati basati su json, come ad esempio json-per-line di 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')
Chiamando `json.tool` dalla riga di comando all'output JSON pretty-print
Dato un file JSON "foo.json" come:
{"foo": {"bar": {"baz": 1}}}
possiamo chiamare il modulo direttamente dalla riga di comando (passando il nome del file come argomento) per stamparlo in modo carino:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
Il modulo prenderà anche input da STDOUT, quindi (in Bash) potremmo fare altrettanto:
$ cat foo.json | python -m json.tool
Formattazione dell'output JSON
Diciamo che abbiamo i seguenti dati:
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Basta scaricare questo come JSON non fa nulla di speciale qui:
>>> print(json.dumps(data))
{"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Impostazione dell'indentazione per ottenere risultati migliori
Se vogliamo una bella stampa, possiamo impostare una dimensione del indent
:
>>> print(json.dumps(data, indent=2))
{
"cats": [
{
"name": "Tubbs",
"color": "white"
},
{
"name": "Pepper",
"color": "black"
}
]
}
Ordinamento dei tasti alfabeticamente per ottenere risultati coerenti
Per impostazione predefinita, l'ordine delle chiavi nell'output non è definito. Possiamo ottenerli in ordine alfabetico per assicurarci di ottenere sempre lo stesso risultato:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
Liberarsi degli spazi bianchi per ottenere risultati compatti
Potremmo desiderare di eliminare gli spazi non necessari, operazione che viene eseguita impostando le stringhe di separazione diverse da ', '
e ': '
predefiniti:
>>>print(json.dumps(data, separators=(',', ':')))
{"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
JSON che codifica oggetti personalizzati
Se solo proviamo il seguente:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
viene visualizzato un errore che dice TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable
.
Per poter serializzare correttamente l'oggetto datetime, è necessario scrivere codice personalizzato per come convertirlo:
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)
e quindi utilizzare questa classe di encoder invece di json.dumps
:
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}