Hvordan skriver jeg JSON-data til en fil?

Jeg har JSON-data gemt i variablen data.

Jeg vil gerne skrive dette til en tekstfil til test, så jeg ikke behøver at hente dataene fra serveren hver gang.

I øjeblikket prøver jeg dette:

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

Og jeg modtager fejlen:

TypeError: must be string or buffer, not dict

Hvordan kan jeg rette dette?

Løsning

Du glemte den egentlige JSON-del - data er en ordbog og endnu ikke JSON-kodet. Skriv det sådan her for at opnå maksimal kompatibilitet (Python 2 og 3):

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

På et moderne system (dvs. Python 3 og UTF-8-understøttelse) kan du skrive en pænere fil med

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

For at få utf8-kodet fil i modsætning til ascii-kodet i det accepterede svar til Python 2 skal du bruge:

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

Koden er enklere i Python 3:

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

På Windows er argumentet encoding='utf-8' til open stadig nødvendigt.

For at undgå at gemme en kodet kopi af dataene i hukommelsen (resultat af dumps) og for at output utf8-kodede bytestrings i både Python 2 og 3, skal du bruge:

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

Kaldet codecs.getwriter er overflødigt i Python 3, men er nødvendigt i Python 2


Læsbarhed og størrelse:

Brugen af ensure_ascii=False giver bedre læsbarhed og mindre størrelse:

>>> 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

Forbedre læsbarheden yderligere ved at tilføje flagene indent=4, sort_keys=True (som foreslået af dinos66) til argumenterne for dump eller dumps. På denne måde får du en pænt indrykket sorteret struktur i json-filen på bekostning af en lidt større filstørrelse.

Kommentarer (18)

Jeg vil svare med en lille ændring i forhold til de førnævnte svar, nemlig at skrive en pænere JSON-fil, som menneskelige øjne bedre kan læse. Til dette formål skal sort_keys overføres som True og indent med 4 mellemrums tegn og du er klar til at gå. Sørg også for at sikre, at ascii-koder ikke bliver skrevet i din JSON-fil:

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