Leggere e scrivere JSON su un file in Python

Introduzione

In questa guida, daremo un'occhiata a come leggere e scrivere dati JSON da e su un file in Python, usando il json modulo.

JSON (notazione oggetto JavaScript) è un formato estremamente popolare per la serializzazione dei dati, dato quanto è generalmente applicabile e leggero, pur essendo abbastanza adatto all'uomo. In particolare, è ampiamente utilizzato nel mondo dello sviluppo web, dove probabilmente incontrerai oggetti serializzati JSON inviati da API REST, configurazione dell'applicazione o anche semplice memorizzazione dei dati.

Data la sua prevalenza, la lettura e l'analisi di file (o stringhe) JSON è piuttosto comune e la scrittura di JSON da inviare è altrettanto comune. In questa guida, daremo un'occhiata a come sfruttare il json modulo per leggere e scrivere JSON in Python.

Scrivere JSON su un file con Python con json.dump() e json.dumps()

Per scrivere contenuti JSON in un file in Python, possiamo usare json.dump() ed json.dumps(). Questi sono metodi separati e ottenere risultati diversi:

  • json.dumps() – Serializza un oggetto in un formato JSON stringa
  • json.dump() – Serializzato un oggetto in un flusso JSON per il salvataggio in file o socket

Nota: La "s" in "dumps" è in realtà l'abbreviazione di "stringa di scarico".

Il formato naturale di JSON è simile a a carta geografica in informatica - una mappa di key-value coppie. In Python, a dizionario è un'implementazione della mappa, quindi saremo naturalmente in grado di rappresentare JSON fedelmente attraverso a dict. Un dizionario può contenere altri dizionari nidificati, matrici, valori booleani o altri tipi primitivi come numeri interi e stringhe.

:::

Nota: Il incorporato json Il pacchetto offre diversi metodi pratici che ci consentono di convertire tra JSON e dizionari.

:::

Detto questo, importiamo il file json modulo, definire un dizionario con alcuni dati e quindi convertirlo in JSON prima di salvarlo in un file:

import json

data = {
    'employees' : [
        {
            'name' : 'John Doe',
            'department' : 'Marketing',
            'place' : 'Remote'
        },
        {
            'name' : 'Jane Doe',
            'department' : 'Software Engineering',
            'place' : 'Remote'
        },
        {
            'name' : 'Don Joe',
            'department' : 'Software Engineering',
            'place' : 'Office'
        }
    ]
}


json_string = json.dumps(data)
print(json_string)

Questo risulta in:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Qui abbiamo un semplice dizionario con pochi employees, ognuno dei quali ha un name, department ed place. dumps() funzione del json modulo discariche un dizionario nei contenuti JSON e restituisce a Stringa JSON.

Una volta serializzato, potresti decidere di inviarlo a un altro servizio che lo deserializzerà o, diciamo, lo memorizzerà. Per archiviare questa stringa JSON in un file, apriremo semplicemente un file in modalità di scrittura e lo annoteremo. Se non vuoi estrarre i dati in una variabile indipendente per un uso successivo e desideri semplicemente scaricarli in un file, puoi saltare il dumps() funzione e uso dump() invece:


with open('json_data.json', 'w') as outfile:
    outfile.write(json_string)


with open('json_data.json', 'w') as outfile:
    json.dump(json_string, outfile)

Qualsiasi oggetto simile a un file può essere passato al secondo argomento di dump() funzione, anche se non è un file effettivo. Un buon esempio di ciò potrebbe essere un socket, che può essere aperto, chiuso e scritto in modo molto simile a un file.

Leggere JSON da un file con Python con json.load() e json.loads()

La mappatura tra i contenuti del dizionario e una stringa JSON è semplice, quindi è facile convertire tra i due. La stessa logica di con dump() ed dumps() viene applicato a load() ed loads(). Molto simile json.dumps(), le json.loads() La funzione accetta una stringa JSON e la converte in un dizionario, mentre json.load() ti permette di caricare in un file:

import json

with open('json_data.json') as json_file:
    data = json.load(json_file)
    print(data)

Questo risulta in:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

In alternativa, leggiamo una stringa JSON in un dizionario:

import json

python_dictionary = json.loads(json_string)
print(python_dictionary)

Che si traduce anche in:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Questo è particolarmente utile per l'analisi delle risposte API REST che inviano JSON. Questi dati ti vengono forniti come una stringa, a cui puoi quindi passare json.loads() direttamente e hai un dizionario molto più gestibile con cui lavorare!

Ordinamento, Pretty-Printing, separatori e codifica

Quando serializzi i tuoi dati in JSON con Python, il formato standard che mira a ridurre al minimo la memoria richiesta per trasmettere i messaggi non è molto leggibile poiché gli spazi bianchi vengono eliminati. Sebbene questo sia il comportamento ideale per il trasferimento dei dati (i computer non si preoccupano della leggibilità, ma si preoccupano delle dimensioni), a volte potrebbe essere necessario apportare piccole modifiche, come l'aggiunta di spazi bianchi per renderlo leggibile dall'uomo.

Dai un'occhiata alla nostra guida pratica e pratica per l'apprendimento di Git, con le migliori pratiche, gli standard accettati dal settore e il cheat sheet incluso. Smetti di cercare su Google i comandi Git e in realtà imparare esso!

Nota: json.dump()/json.dumps() ed json.load()/json.loads() tutti forniscono alcune opzioni di formattazione.

JSON abbastanza stampabile in Python

Rendere JSON leggibile dall'uomo (aka "bella stampa") è facile come passare un valore intero per the indent parametro:

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, indent=4))

Questo crea un rientro di 4 spazi su ogni nuovo blocco logico:

{
    "people": [
        {
            "website": "stackabuse.com", 
            "from": "Nebraska", 
            "name": "Scott"
        }
    ]
}

Un'altra opzione è utilizzare lo strumento della riga di comando: json.tool. Con esso, puoi stampare in modo grazioso il JSON nella riga di comando senza influire sulla stringa trasmessa e influire solo sul modo in cui viene visualizzato sulla pipe di output standard:

$ echo '{"people":[{"name":"Scott", "website":"stackabuse.com", "from":"Nebraska"}]}' | python -m json.tool
{
    "people": [
        {
            "name": "Scott",
            "website": "stackabuse.com"
            "from": "Nebraska",
        }
    ]
}

Ordinamento di oggetti JSON per chiavi

In termini JSON:

"Un oggetto è un insieme non ordinato di coppie nome/valore."

L'ordine delle chiavi non è garantito, ma è possibile che tu debba imporre l'ordine delle chiavi. Per ottenere l'ordine, puoi passare True Vai all’email sort_keys opzione quando si utilizza json.dump() or json.dumps():

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, sort_keys=True, indent=4))

Questo risulta in:

{
    "people": [
        {
            "from": "Nebraska",
            "name": "Scott",
            "website": "stackabuse.com"
        }
    ]
}

Testo e codifica ASCII

Per impostazione predefinita, json.dump() ed json.dumps() assicurerà che il testo nel dizionario Python dato sia codificato in ASCII. Se sono presenti caratteri non ASCII, vengono automaticamente sottoposti a escape, come mostrato nell'esempio seguente:

import json
data = {'item': 'Beer', 'cost':'£4.00'}
jstr = json.dumps(data, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "u00a34.00"
}

Questo non è sempre accettabile e in molti casi potresti voler mantenere invariati i tuoi caratteri Unicode. Per fare ciò, impostare il ensure_ascii opzione a False:

jstr = json.dumps(data, ensure_ascii=False, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "£4.00"
}

Salta tipi di dati chiave personalizzati

Se una chiave nel dizionario è di tipo non primitivo (str, int, float, bool or None) Del TypeError viene generato quando si tenta di eseguire il dump dei contenuti JSON in un file. Puoi saltare questi tasti tramite il file skipkeys argomento:

jstr = json.dumps(data, skipkeys=True)

Abilitazione e disabilitazione del controllo circolare

Se una proprietà di un oggetto JSON fa riferimento a se stessa o a un altro oggetto che fa riferimento all'oggetto padre, viene creato un JSON infinitamente ricorsivo. La ricorsione infinita in genere comporta l'allocazione rapida della memoria fino a quando un dispositivo non esaurisce la memoria e, in caso di dumping JSON, a RecursionError viene sollevato e lo scarico viene interrotto.

Questo è regolato dal check_circular bandiera, che è True per impostazione predefinita e previene possibili problemi durante la scrittura di dipendenze circolari. Per disattivarlo, puoi impostarlo su `False:

jstr = json.dumps(data, check_circular=False)

Tieni presente, tuttavia, che questo è vivamente non consigliato.

Abilitare e disabilitare i NaN

NaN-valori, come ad esempio -inf, inf ed nan potrebbe insinuarsi negli oggetti che si desidera serializzare o deserializzare. standard JSON non consente per i valori NaN, ma portano comunque un valore logico che potresti voler trasmettere in un messaggio. D'altra parte, potresti voler imporre quei valori NaN non trasmesso e sollevare invece un'eccezione. Il allow_nan flag è impostato su True per impostazione predefinita e consente di serializzare e deserializzare i valori NaN, sostituendoli con gli equivalenti JavaScript (Inifinity, -Infinity ed NaN).

Se imposti il ​​flag su False invece, passerai a un formato rigorosamente standardizzato JSON, che genera a ValueError se i tuoi oggetti contengono attributi con questi valori:

jstr = json.dumps(data, allow_nan=False)

Cambiare separatori

In JSON, le chiavi sono separate dai valori con i due punti (:) e gli elementi sono separati l'uno dall'altro con virgole (,):

key1:value1,
key2:value2

I separatori predefiniti per leggere e scrivere JSON in Python sono (', ', ': ') con spazi bianchi dopo le virgole e i due punti. Puoi modificarli per saltare gli spazi bianchi e quindi rendere il JSON un po' più compatto, oppure cambiare completamente i separatori con altri caratteri speciali per una rappresentazione diversa:


jstr = json.dumps(data, separators=(',', ':'))

Problemi di compatibilità con Python 2

Se stai usando una versione precedente di Python (2.x), potresti imbatterti in un file TypeError durante il tentativo di scaricare i contenuti JSON in un file. Vale a dire, se i contenuti contengono un carattere non ASCII, a TypeError è sollevato, anche se si passa l'argomento encoding, quando si utilizza il file json.dump() Metodo:


with open('json_data.json', 'w', encoding='utf-8') as outfile:
    json.dump(json_string, outfile, ensure_ascii=False)

Se incontri questo caso limite, che da allora è stato risolto nelle successive versioni di Python, prova a utilizzare json.dumps() invece, e scrivi il contenuto della stringa in un file invece di eseguire lo streaming del contenuto direttamente in un file.

Conclusione

In questa guida, ti abbiamo presentato il json.dump(), json.dumps(), json.load()e json.loads() metodi, che aiutano a serializzare e deserializzare le stringhe JSON.

Abbiamo quindi dato un'occhiata a come ordinare gli oggetti JSON, stamparli in modo grazioso, modificare la codifica, ignorare i tipi di dati chiave personalizzati, abilitare o disabilitare i controlli circolari e se i NaN sono consentiti, nonché come modificare i separatori per serializzazione e deserializzazione.

Poiché JSON è uno dei modi più popolari per serializzare i dati strutturati, è probabile che tu debba interagire con esso abbastanza frequentemente, specialmente quando lavori su applicazioni web. di pitone json module è un ottimo modo per iniziare, anche se probabilmente lo troverai simplejson è un'altra ottima alternativa che è molto meno rigida sulla sintassi JSON.

Timestamp:

Di più da Impilamento