Come posso scrivere i dati JSON in un file?


1122

Ho i dati JSON memorizzati nella variabile data.

Voglio scrivere questo in un file di testo per il test, quindi non devo prendere i dati dal server ogni volta.

Attualmente sto provando questo:

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

E sto ricevendo questo errore:

TypeError: deve essere stringa o buffer, non dict

Come risolvere questo?

Risposte:


2042

Hai dimenticato l'attuale parte JSON: dataè un dizionario e non è ancora codificato 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 (ad es. Supporto per Python 3 e UTF-8), puoi scrivere un file più bello con

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

8
questo potrebbe essere utile per la serializzazione: stackoverflow.com/questions/4512982/...
jedierikb

12
Intendi json.dump o json.dumps?
TerminalDilettante

153
@TerminalDilettante json.dumpscrive su un file o un oggetto simile a un file, mentre json.dumpsrestituisce una stringa.
phihag,

24
btw: per leggere di nuovo i dati usare: con open ('data.txt') come infile: d = json.load (infile). Vedi: questa risposta
klaas

9
@denvar No, questa risposta è ottimizzata. Su Python 3, json.dumpscrive su un file di testo, non su un file binario. Otterresti un TypeErrorse il file è stato aperto con wb. Nelle versioni più vecchie di Python, entrambi wnand wblavoro. Una codifica esplicita non è necessaria poiché l'output di json.dumpè ASCII solo per impostazione predefinita. Se puoi essere sicuro che il tuo codice non viene mai eseguito su versioni Python legacy e tu e il gestore del file JSON potete gestire correttamente i dati non ASCII, potete specificarne uno e impostarlo ensure_ascii=False.
phihag,

267

Per ottenere il file codificato utf8 anziché codificato ASCII nella risposta accettata per Python 2, utilizzare:

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' encoding='utf-8'argomento openè ancora necessario.

Per evitare di archiviare una copia codificata dei dati in memoria (risultato di dumps) e di generare i bytestring codificati in utf8 in Python 2 e 3, usare:

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

La codecs.getwriterchiamata è ridondante in Python 3 ma richiesta per Python 2


Leggibilità e dimensioni:

L'uso di ensure_ascii=Falseoffre una migliore leggibilità e dimensioni ridotte:

>>> 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 flag indent=4, sort_keys=True(come suggerito da dinos66 ) agli argomenti di dumpo dumps. In questo modo otterrai una struttura ordinata ben rientrata nel file json al costo di una dimensione del file leggermente più grande.


5
Il unicodeè superfluo - il risultato di json.dumpsè già un oggetto Unicode. Si noti che ciò non riesce in 3.x, dove è stato ripulito l'intero casino della modalità file di output e json usa sempre stringhe di caratteri (e I / O di caratteri) e mai byte.
phihag,

4
In 2.x type(json.dumps('a'))è <type 'str'>. Anche lo type(json.dumps('a', encoding='utf8'))è <type 'str'>.
Antony Hatchkins,

4
Sì, in 3.x json utilizza le stringhe, tuttavia la codifica predefinita è ascii. Devi dire esplicitamente che vuoi utf8anche in 3.x. Aggiornato la risposta.
Antony Hatchkins,

4
Oh, hai perfettamente ragione, devo aver confuso qualcosa. +1 per il dettaglio.
phihag,

1
La risposta di Python 3.x ha funzionato per me anche se sto usando 2.7. La risposta 2.x ha restituito un errore: 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128). Quindi, in caso di dubbio, usa la risposta 3.x!
Blairg23,

162

Vorrei rispondere con una leggera modifica con le risposte di cui sopra e cioè scrivere un file JSON predefinito che gli occhi umani possano leggere meglio. Per questo, passa sort_keyscome Truee indentcon 4 caratteri spaziali e sei a posto. Inoltre, assicurati 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)

2
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
sto

1
@SirBenBenji Assicurarsi che la stringa che si sta tentando di scrivere segua: str.decode ('utf-8').
Ambodi

1
@SirBenBenji Puoi provare a usare anche i codec, come specificato da dinos66 di seguito
Shiv

Devi anche dichiarare la tua codifica aggiungendo # -*- coding: utf-8 -*-dopo lo shebang
aesede

2
+1 per sort_key e rientro. @aesede Non va bene aggiungere questa riga perché farà sembrare che questa soluzione funzioni anche con python2, cosa che non funziona ( UnicodeEncodeErrorcon dati non ascii). Vedi la mia soluzione per i dettagli.
Antony Hatchkins,

111

Leggi e scrivi file JSON con Python 2 + 3; funziona con unicode

# -*- coding: utf-8 -*-
import json

# Make it work for Python 2+3 and with Unicode
import io
try:
    to_unicode = unicode
except NameError:
    to_unicode = str

# Define data
data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
        'a string': 'bla',
        'another dict': {'foo': 'bar',
                         'key': 'value',
                         'the answer': 42}}

# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
    str_ = json.dumps(data,
                      indent=4, sort_keys=True,
                      separators=(',', ': '), ensure_ascii=False)
    outfile.write(to_unicode(str_))

# Read JSON file
with open('data.json') as data_file:
    data_loaded = json.load(data_file)

print(data == data_loaded)

Spiegazione dei parametri di json.dump:

  • indent: Utilizzare 4 spazi per rientrare in ciascuna voce, ad esempio quando viene avviato un nuovo dict (altrimenti tutti saranno in una riga),
  • sort_keys: ordina le chiavi dei dizionari. Ciò è utile se si desidera confrontare i file json con uno strumento diff / metterli sotto il controllo della versione.
  • separators: Per impedire a Python di aggiungere spazi bianchi finali

Con un pacco

Dai un'occhiata al mio pacchetto di utilità mpuper uno super semplice e facile da ricordare:

import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)

File JSON creato

{
    "a list":[
        1,
        42,
        3.141,
        1337,
        "help",
        "€"
    ],
    "a string":"bla",
    "another dict":{
        "foo":"bar",
        "key":"value",
        "the answer":42
    }
}

Terminazioni di file comuni

.json

alternative

Per la tua applicazione, potrebbe essere importante quanto segue:

  • Supporto da altri linguaggi di programmazione
  • Performance di lettura / scrittura
  • Compattezza (dimensione del file)

Vedi anche: Confronto dei formati di serializzazione dei dati

Nel caso in cui tu stia cercando un modo per creare file di configurazione, potresti voler leggere il mio breve articolo File di configurazione in Python


2
Si noti che il force_asciiflag è Truepredefinito. Avrai "\u20ac"sequenze illeggibili di 6 byte per ognuna nel tuo file json (così come di qualsiasi altro carattere non ascii).
Antony Hatchkins,

Perché usi openper leggere ma io.openper scrivere? È possibile utilizzare anche io.openper la lettura? In tal caso, quali parametri devono essere passati?
Micah Zoltu il

23

Per quelli di voi che stanno provando a scaricare il greco o altre lingue "esotiche" come me ma hanno anche problemi (errori unicode) con caratteri strani come il simbolo di pace (\ u262E) o altri che sono spesso contenuti in dati formattati json come Twitter, la soluzione potrebbe essere la seguente (sort_keys è ovviamente facoltativo):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))

1
+1 Mentre docs raccomanda python3 builtin opene l'assotiated io.openover codecs.open, in questo caso è anche un bel trucco compatibile con le versioni precedenti. In python2 codecs.openè più "onnivoro" di io.open (può "mangiare" sia str che unicode, convertendolo se necessario). Si può dire che questa codecs.openstranezza compensa la json.dumpsstranezza della generazione di diversi tipi di oggetti ( str/ unicode) a seconda della presenza delle stringhe unicode nell'input.
Antony Hatchkins,

10

Non ho abbastanza reputazione da aggiungere nei commenti, quindi scrivo solo alcune delle mie scoperte di questo fastidioso TypeError qui:

Fondamentalmente, penso che sia un bug nella json.dump()funzione solo in Python 2 - Non è possibile scaricare un dato Python (dizionario / elenco) contenente caratteri non ASCII, anche se si apre il file con il encoding = 'utf-8'parametro. (vale a dire qualunque cosa tu faccia). Ma, json.dumps()funziona sia su Python 2 e 3.

Per illustrare ciò, seguendo la risposta di phihag: il codice nella sua risposta si rompe in Python 2 con l'eccezione TypeError: must be unicode, not str, se datacontiene caratteri non ASCII. (Python 2.7.6, Debian):

import json
data = {u'\u0430\u0431\u0432\u0433\u0434': 1} #{u'абвгд': 1}
with open('data.txt', 'w') as outfile:
    json.dump(data, outfile)

Funziona comunque bene in Python 3.


Fornisci dei motivi quando affermi che qualcosa non va. Usa @nickname in modo che la persona riceva una notifica. Non puoi scrivere commenti, ma puoi leggere commenti. Come già affermato nella mia risposta al primo commento, prova data = {'asdf': 1}. Otterrai il famigerato TypeErrorcon la tua (seconda) variante.
Antony Hatchkins,

Per quanto riguarda ensure_ascii- è necessario se si desidera ottenere un output utf8 "reale". Senza di essa avrai ascii semplici con 6 byte per lettera russa anziché 2 byte per carattere con questo flag.
Antony Hatchkins,

@AntonyHatchkins Hai ragione per la unicode()parte. Ho appena realizzato per ioil pacchetto in Python 2, write()ha bisogno unicode, non è str.
ibico,

1
Questo codice funziona anche con python2.6.6, Debian (10 dicembre 2010). Così come con python2.7.9 o python3. Controllalo ancora una volta, per favore.
Antony Hatchkins,

7

Scrivi un dato nel file usando JSON usando json.dump () o json.dumps () usato. scrivere in questo modo per archiviare i dati nel file.

import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
    json.dump(data, txtfile)

questo esempio nell'elenco è memorizzato in un file.


è simile ma fornisce un esempio
Vishal Gediya,

5

Per scrivere il JSON con rientro, "bella stampa":

import json

outfile = open('data.json')
json.dump(data, outfile, indent=4)

Inoltre, se è necessario eseguire il debug di JSON formattato in modo errato e si desidera un messaggio di errore utile, utilizzare la import simplejsonlibreria anziché import json(le funzioni dovrebbero essere le stesse)


4
json.dump(data, open('data.txt', 'wb'))

2
Questo fa la stessa cosa della risposta di @ phihag, ma non è garantito che funzioni sempre. Consideriamo tale codice: f = open('1.txt', 'w'); f.write('a'); input(). Eseguilo e poi SYGTERM ( Ctrl-Zquindi kill %1su Linux, Ctrl-Breaksu Windows). 1.txtavrà 0 byte. È perché la scrittura è stata memorizzata nel buffer e il file non è stato né scaricato, né chiuso nel momento in cui si è verificato SYGTERM. withblock garantisce che il file venga sempre chiuso proprio come fa il blocco 'try / finally' ma più breve.
Antony Hatchkins,

3

Scrittura di JSON in un file

import json

data = {}
data['people'] = []
data['people'].append({
    'name': 'Scott',
    'website': 'stackabuse.com',
    'from': 'Nebraska'
})
data['people'].append({
    'name': 'Larry',
    'website': 'google.com',
    'from': 'Michigan'
})
data['people'].append({
    'name': 'Tim',
    'website': 'apple.com',
    'from': 'Alabama'
})

with open('data.txt', 'w') as outfile:
    json.dump(data, outfile)

Lettura di JSON da un file

import json

with open('data.txt') as json_file:
    data = json.load(json_file)
    for p in data['people']:
        print('Name: ' + p['name'])
        print('Website: ' + p['website'])
        print('From: ' + p['from'])
        print('')

Benvenuto in Stack Overflow. Se decidi di rispondere a una domanda precedente con risposte ben definite e corrette, l'aggiunta di una nuova risposta a fine giornata potrebbe non farti ottenere alcun credito. Se hai alcune nuove informazioni distintive, o sei convinto che le altre risposte siano tutte sbagliate, aggiungi sicuramente una nuova risposta, ma "l'ennesima risposta" fornisce le stesse informazioni di base molto tempo dopo che la domanda è stata generalmente vinta " ti guadagno molto credito. (Tu mostri alcuni dati di esempio; va bene, ma non sono sicuro che sia abbastanza, soprattutto perché non mostri cosa viene prodotto per i dati di esempio.)
Jonathan Leffler,

Ok grazie per la guida
iman

2

se stai cercando di scrivere un frame di dati Panda in un file usando un formato JSON, lo consiglierei

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()

2

Tutte le risposte precedenti sono corrette qui è un esempio molto semplice:

#! /usr/bin/env python
import json

def write_json():
    # create a dictionary  
    student_data = {"students":[]}
    #create a list
    data_holder = student_data["students"]
    # just a counter
    counter = 0
    #loop through if you have multiple items..         
    while counter < 3:
        data_holder.append({'id':counter})
        data_holder.append({'room':counter})
        counter += 1    
    #write the file        
    file_path='/tmp/student_data.json'
    with open(file_path, 'w') as outfile:
        print("writing file to: ",file_path)
        # HERE IS WHERE THE MAGIC HAPPENS 
        json.dump(student_data, outfile)
    outfile.close()     
    print("done")

write_json()

inserisci qui la descrizione dell'immagine


1

La risposta accettata va bene. Tuttavia, ho riscontrato l'errore "non è json serializzabile" utilizzando quello.

Ecco come l'ho risolto con open("file-name.json", 'w')come output:

output.write(str(response))

Anche se non è una buona soluzione in quanto il file json che crea non avrà doppie virgolette, tuttavia è ottimo se stai cercando veloce e sporco.


0

I dati JSON possono essere scritti in un file come segue

hist1 = [{'val_loss': [0.5139984398465246],
'val_acc': [0.8002029867684085],
'loss': [0.593220705309384],
'acc': [0.7687131817929321]},
{'val_loss': [0.46456472964199463],
'val_acc': [0.8173602046780344],
'loss': [0.4932038113037539],
'acc': [0.8063946213802453]}]

Scrivi in ​​un file:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.