Hur skriver jag JSON-data till en fil?

Jag har JSON-data lagrat i variabeln data.

Jag vill skriva detta till en textfil för testning så att jag inte behöver hämta data från servern varje gång.

För närvarande försöker jag med följande:

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

Och får felet:

TypeError: måste vara sträng eller buffert, inte dict.

Hur åtgärdar jag detta?

Lösning

Du glömde den faktiska JSON-delen - data är en ordbok och ännu inte JSON-kodad. Skriv det så här för maximal kompatibilitet (Python 2 och 3):

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

På ett modernt system (dvs. Python 3 och stöd för UTF-8) kan du skriva en snyggare 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)

För att få en utf8-kodad fil i motsats till ascii-kodad i det accepterade svaret för Python 2, använd:

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

Koden är enklare i Python 3:

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

På Windows är argumentet encoding='utf-8' till open fortfarande nödvändigt.

För att undvika att lagra en kodad kopia av data i minnet (resultat av dumps) och för att ge ut utf8-kodade bytestringar i både Python 2 och 3, använd:

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

Kallelsen codecs.getwriter är överflödig i Python 3 men nödvändig för Python 2.


Läsbarhet och storlek:

Användningen av ensure_ascii=False ger bättre läsbarhet och mindre storlek:

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

Förbättra läsbarheten ytterligare genom att lägga till flaggorna indent=4, sort_keys=True (enligt förslag från dinos66) till argumenten för dump eller dumps. På så sätt får du en snyggt indragen sorterad struktur i json-filen till priset av en något större filstorlek.

Kommentarer (18)

Jag skulle svara med en liten ändring av de tidigare nämnda svaren och det är att skriva en finare JSON-fil som människans ögon kan läsa bättre. För detta, skicka sort_keys som True och indent med 4 mellanslagstecken och du är klar. Se också till att asciikoderna inte skrivs in 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)