Как да запиша JSON данни във файл?

Имам JSON данни, съхранени в променливата data.

Искам да ги запиша в текстов файл за тестване, за да не се налага всеки път да вземам данните от сървъра.

В момента се опитвам да направя следното:

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

И получавам грешката:

TypeError: must be string or buffer, not dict

Как да поправя това?

Решение

Забравили сте същинската част на JSON - data е речник и все още не е кодиран в JSON. Запишете го по този начин за максимална съвместимост (Python 2 и 3):

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

На съвременна система (т.е. Python 3 и поддръжка на UTF-8) можете да напишете по-хубав файл с

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
Коментари (21)

За да получите utf8-encoded файл за разлика от ascii-encoded в приетия отговор за Python 2, използвайте:

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

Кодът е по-прост в Python 3:

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

В Windows все още е необходим аргументът encoding='utf-8' към open.

За да се избегне съхраняването на кодирано копие на данните в паметта (резултат от dumps) и за да се извеждат utf8-кодирани байтстрийги както в Python 2, така и в Python 3, използвайте:

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

Извикването на codecs.getwriter е излишно в Python 3, но е необходимо за Python 2.


Четене и размер:

Използването на ensure_ascii=False осигурява по-добра четимост и по-малък размер:

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

Допълнително подобрете четимостта, като добавите флаговете indent=4, sort_keys=True (както е предложено от dinos66) към аргументите на dump или dumps. По този начин ще'получите хубава сортирана структура с отстъп в json файла за сметка на малко по-голям размер на файла.

Коментари (18)

Бих отговорил с малка модификация на гореспоменатите отговори, а именно да напишете прецизиран JSON файл, който човешките очи могат да прочетат по-добре. За тази цел подайте sort_keys като True и indent с 4 символа интервал и всичко е готово. Също така се уверете, че ascii кодовете няма да бъдат записани във вашия JSON файл:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
Коментари (5)