Come posso scrivere dati JSON in un file?

Ho dei dati JSON memorizzati nella variabile data.

Voglio scriverli in un file di testo per i test in modo da non dover prendere i dati dal server ogni volta.

Attualmente, sto provando questo:

obj = open('data.txt', 'wb')
obj.write(data)
obj.close

E sto ricevendo l'errore:

TypeError: must be string or buffer, not dict

Come risolvere questo problema?

Soluzione

Hai dimenticato la parte JSON vera e propria - data è un dizionario e non è ancora codificato in JSON. Scrivilo così per la massima compatibilità (Python 2 e 3):

import json
with open('data.json', 'w') as f:
    json.dump(data, f)

Su un sistema moderno (cioè Python 3 e supporto UTF-8), puoi scrivere un file più carino con

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
Commentari (21)

Per ottenere file utf8-encoded invece di ascii-encoded nella risposta accettata per Python 2 usare:

import io, json
with io.open('data.txt', 'w', encoding='utf-8') as f:
  f.write(json.dumps(data, ensure_ascii=False))

Il codice è più semplice in Python 3:

import json
with open('data.txt', 'w') as f:
  json.dump(data, f, ensure_ascii=False)

Su Windows, l'argomento encoding='utf-8'per open è ancora necessario.

Per evitare di memorizzare una copia codificata dei dati in memoria (risultato di dumps) e per emettere bytestring utf8-encoded sia in Python 2 che 3, usare:

import json, codecs
with open('data.txt', 'wb') as f:
    json.dump(data, codecs.getwriter('utf-8')(f), ensure_ascii=False)

La chiamata codecs.getwriter è ridondante in Python 3 ma necessaria per Python 2.


Leggibilità e dimensioni:

L'uso di ensure_ascii=False dà una migliore leggibilità e dimensioni minori:

>>> json.dumps({'price': '€10'})
'{"price": "\\u20ac10"}'
>>> json.dumps({'price': '€10'}, ensure_ascii=False)
'{"price": "€10"}'

>>> len(json.dumps({'абвгд': 1}))
37
>>> len(json.dumps({'абвгд': 1}, ensure_ascii=False).encode('utf8'))
17

Migliorare ulteriormente la leggibilità aggiungendo i flag indent=4, sort_keys=True (come suggerito da dinos66) agli argomenti di dump o dumps. In questo modo si otterrà una struttura ordinata e ben indentata nel file json al costo di una dimensione del file leggermente maggiore.

Commentari (18)

Risponderei con una leggera modifica con le risposte di cui sopra e che è quello di scrivere un file JSON pretestuoso che gli occhi umani possono leggere meglio. Per questo, passa sort_keys come True e indent con 4 caratteri di spazio e sei a posto. Assicurati anche che i codici ascii non vengano scritti nel tuo file JSON:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
Commentari (5)