Как мне записать данные JSON в файл?
У меня есть данные JSON, хранящиеся в переменной data
,
Я хочу записать это в текстовый файл для тестирования, чтобы мне не приходилось каждый раз получать данные с сервера.
В настоящее время я пытаюсь это:
obj = open('data.txt', 'wb')
obj.write(data)
obj.close
И получаю ошибку:
TypeError: must be string or buffer, not dict
Как это исправить?
18 ответов
Вы забыли фактическую часть JSON- data
это словарь и еще не в JSON-кодировке. Напишите это так:
import json
with open('data.json', 'w') as outfile:
json.dump(data, outfile)
Примечание: работает на 3.x и 2.x .
Чтобы получить файл с кодировкой utf8, а не кодированный ascii в принятом ответе для 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 и 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 за счет немного большего размера файла.
Я бы ответил с небольшими изменениями с вышеупомянутыми ответами, а именно, чтобы написать предварительно подтвержденный файл 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)
Чтение и запись файлов JSON с помощью Python 2+3; работает с юникодом
# -*- 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)
Пояснение параметров json.dump
:
indent
: Используйте 4 пробела для отступа каждой записи, например, когда начинается новый dict (иначе все будут в одной строке),sort_keys
: сортировать ключи словарей. Это полезно, если вы хотите сравнить файлы json с помощью инструмента сравнения / поставить их под контроль версий.separators
: Запретить Python добавлять конечные пробелы
С пакетом
Посмотрите на мой пакет утилит mpu
для супер просто и легко запомнить:
import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)
Создан файл JSON
{
"a list":[
1,
42,
3.141,
1337,
"help",
"€"
],
"a string":"bla",
"another dict":{
"foo":"bar",
"key":"value",
"the answer":42
}
}
Общие окончания файлов
.json
альтернативы
- CSV: супер простой формат ( чтение и запись)
- JSON: Отлично подходит для написания удобочитаемых данных; ОЧЕНЬ широко используется ( чтение и запись)
- YAML: YAML - это расширенный набор JSON, но его легче читать ( чтение и запись, сравнение JSON и YAML).
- pickle: формат сериализации Python ( чтение и запись)
- MessagePack ( пакет Python): более компактное представление ( чтение и запись)
- HDF5 ( пакет Python): отлично подходит для матриц ( чтение и запись)
- XML: существует тоже * вздох * ( чтение и запись)
Для вашего приложения может быть важно следующее:
- Поддержка другими языками программирования
- Чтение / запись производительности
- Компактность (размер файла)
Смотрите также: Сравнение форматов сериализации данных
Если вы предпочитаете создавать конфигурационные файлы, вы можете прочитать мою короткую статью Конфигурационные файлы в Python
Для тех из вас, кто пытается сбросить греческий или другие "экзотические" языки, такие как я, но также имеют проблемы (ошибки Юникода) со странными символами, такими как символ мира (\u262E) или другими, которые часто содержатся в данных, отформатированных в json например, Twitter, решение может быть следующим (sort_keys явно необязателен):
import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
Запись JSON в файл
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)
Чтение JSON из файла
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('')
У меня недостаточно репутации, чтобы добавлять комментарии, поэтому я просто напишу некоторые из своих выводов об этой надоедливой ошибке TypeError здесь:
В принципе, я думаю, что это ошибка в json.dump()
функция только в Python 2 - она не может вывести данные Python (словарь / список), содержащие не-ASCII символы, даже если вы откроете файл с помощью encoding = 'utf-8'
параметр. (т.е. независимо от того, что вы делаете). Но, json.dumps()
работает на Python 2 и 3.
Чтобы проиллюстрировать это, проследим за ответом phihag: код в его ответе разрывается в Python 2 за исключением TypeError: must be unicode, not str
, если data
содержит символы не 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)
Тем не менее, он отлично работает в Python 3.
Запишите данные в файл, используя JSON, используя json.dump() или json.dumps(). напишите так, чтобы сохранить данные в файле.
import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
json.dump(data, txtfile)
этот пример в списке хранится в файл.
Чтобы написать JSON с отступом "pretty print":
import json
outfile = open('data.json')
json.dump(data, outfile, indent=4)
Кроме того, если вам нужно отладить неправильно отформатированный JSON и получить полезное сообщение об ошибке, используйте import simplejson
библиотека, а не import json
(функции должны быть одинаковыми)
Все предыдущие ответы верны, вот очень простой пример:
#! /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()
Для людей, которым нравятся однострочники (следовательно, оператор не вариант), более чистый метод, чем оставлять висячий открытый дескриптор файла, может заключаться в использованииwrite_text
отpathlib
и сделайте что-то вроде ниже:
pathlib.Path("data.txt").write_text(json.dumps(data))
Это может быть удобно в некоторых случаях в контекстах, где операторы не разрешены, например:
[pathlib.Path(f"data_{x}.json").write_text(json.dumps(x)) for x in [1, 2, 3]]
Я не утверждаю, что его следует предпочестьwith
(и это, вероятно, медленнее), просто еще один вариант.
Прежде чем записать словарь в файл в виде json, вы должны превратить этот словарь в строку json, используяjson
библиотека.
import json
data = {
"field1":{
"a": 10,
"b": 20,
},
"field2":{
"c": 30,
"d": 40,
},
}
json_data = json.dumps(json_data)
А также вы можете добавить отступ к данным json, чтобы выглядеть красивее.
json_data = json.dumps(json_data, indent=4)
Если вы хотите отсортировать ключи перед преобразованием в json,
json_data = json.dumps(json_data, sort_keys=True)
Вы также можете использовать комбинацию этих двух.
Обратитесь к документации json здесь, чтобы узнать о гораздо большем количестве функций.
Наконец, вы можете записать в файл json
f = open('data.json', 'wb')
f.write(json_data)
Данные JSON могут быть записаны в файл следующим образом
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]}]
Написать в файл:
with open('text1.json', 'w') as f:
json.dump(hist1, f)
Если вы пытаетесь записать pandas dataframe в файл в формате json, я бы порекомендовал это
destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
Принятый ответ в порядке. Тем не менее, я столкнулся с ошибкой "не json serializable", используя это.
Вот как я исправил это с помощью open("file-name.json", 'w') в качестве вывода:
output.write (ул (ответ))
Хотя это не очень удачное решение, так как создаваемый файл json не будет содержать двойных кавычек, однако будет неплохо, если вы ищете быстрый и грязный файл.
Вот полезная структура для чтения и записи файла в Python 3.
from json import dump, load
from time import sleep
from random import random
def json_file(path, data = None, delay = 0.1):
while True:
try:
if data == None:
with open(path, "r", encoding = "utf-8") as f:
return load(f)
else:
with open(path, "w", encoding = "utf-8") as f:
return dump(data, f)
except:
sleep(random()*delay) # concurrency
Если в словаре есть типы данных NumPy,
json.dumps()
требуется дополнительный параметр, кредиты переходят в TypeError: объект типа 'ndarray' не сериализуемый JSON , и он также исправит такие ошибки, как
TypeError: Object of type int64 is not JSON serializable
и так далее:
class NumpyEncoder(json.JSONEncoder):
""" Special json encoder for np types """
def default(self, obj):
if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
np.int16, np.int32, np.int64, np.uint8,
np.uint16, np.uint32, np.uint64)):
return int(obj)
elif isinstance(obj, (np.float_, np.float16, np.float32,
np.float64)):
return float(obj)
elif isinstance(obj, (np.ndarray,)):
return obj.tolist()
return json.JSONEncoder.default(self, obj)
А затем запустите:
import json
#print(json.dumps(my_data[:2], indent=4, cls=NumpyEncoder)))
with open(my_dir+'/my_filename.json', 'w') as f:
json.dumps(my_data, indent=4, cls=NumpyEncoder)))
Вы также можете захотеть вернуть строку вместо списка в случае np.array(), поскольку массивы печатаются как списки, распределенные по строкам, что приведет к увеличению вывода, если у вас есть большие или много массивов. Предостережение: позже будет труднее получить доступ к элементам из сброшенного словаря, чтобы вернуть их в виде исходного массива. Тем не менее, если вы не против иметь только строку массива, это сделает словарь более читабельным. Затем обменяйте:
elif isinstance(obj, (np.ndarray,)):
return obj.tolist()
с участием:
elif isinstance(obj, (np.ndarray,)):
return str(obj)
или просто:
else:
return str(obj)