Вы можете попробовать это.
>>> import ast
>>> data = "{'user': 'bob', 'age': 10, 'grades': ['A', 'F', 'C']}"
>>> ast.literal_eval(data)
O/P: {'age': 10, 'grades': ['A', 'F', 'C'], 'user': 'bob'}
>>> user = ast.literal_eval(data)
>>> user['age']
O/P: 10
>>> user['grades']
O/P: ['A', 'F', 'C']
>>> user['user']
O/P: 'bob'
Я предполагаю, что ваш JSON-файл будет декодироваться в список словарей. Сначала нам нужна функция, которая сгладит объекты JSON:
def flattenjson( b, delim ):
val = {}
for i in b.keys():
if isinstance( b[i], dict ):
get = flattenjson( b[i], delim )
for j in get.keys():
val[ i + delim + j ] = get[j]
else:
val[i] = b[i]
return val
Результат выполнения этого фрагмента на вашем объекте JSON:
flattenjson( {
"pk": 22,
"model": "auth.permission",
"fields": {
"codename": "add_message",
"name": "Can add message",
"content_type": 8
}
}, "__" )
is
{
"pk": 22,
"model": "auth.permission',
"fields__codename": "add_message",
"fields__name": "Can add message",
"fields__content_type": 8
}
После применения этой функции к каждому dict во входном массиве объектов JSON:
input = map( lambda x: flattenjson( x, "__" ), input )
и поиске соответствующих имен столбцов:
columns = [ x for row in input for x in row.keys() ]
columns = list( set( columns ) )
нетрудно запустите это через модуль csv:
with open( fname, 'wb' ) as out_file:
csv_w = csv.writer( out_file )
csv_w.writerow( columns )
for i_r in input:
csv_w.writerow( map( lambda x: i_r.get( x, "" ), columns ) )
Надеюсь, это поможет!
JSON может представлять собой широкий спектр структур данных - объект JS «примерно похож на Python dict (со строковыми ключами), JS« массив », примерно как список Python, и вы можете вложить их до тех пор, пока конечные «листовые» элементы - это числа или строки.
CSV может по существу представлять только двухмерную таблицу - необязательно с первой строкой «заголовков», то есть «имена столбцов», которые могут таблица, интерпретируемая как список dicts, вместо обычной интерпретации, список списков (опять же, «листовые» элементы могут быть числами или строками).
Итак, в общем случае вы можете ' t переводит произвольную структуру JSON в CSV. В нескольких особых случаях вы можете (массив массивов без дальнейшего вложения, массивы объектов, все из которых имеют одинаковые ключи). Какой особый случай, если таковой имеется, относится к вашей проблеме? Детали решения зависят от того, какой особый случай у вас есть. Учитывая удивительный факт, что вы даже не упоминаете, какой из них применим, я подозреваю, что вы, возможно, не считали ограничение, ни одно из применимых случаев на самом деле не применяется, и ваша проблема невозможна. Но проясните!
У меня возникли проблемы с предложенным решением Дэна , но это сработало для меня:
import json
import csv
f = open('test.json')
data = json.load(f)
f.close()
f=csv.writer(open('test.csv','wb+'))
for item in data:
f.writerow([item['pk'], item['model']] + item['fields'].values())
Где «test.json» содержало следующее:
[
{"pk": 22, "model": "auth.permission", "fields":
{"codename": "add_logentry", "name": "Can add log entry", "content_type": 8 } },
{"pk": 23, "model": "auth.permission", "fields":
{"codename": "change_logentry", "name": "Can change log entry", "content_type": 8 } }, {"pk": 24, "model": "auth.permission", "fields":
{"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 8 } }
]
Этот код должен работать на вас, предполагая, что ваши данные JSON находятся в файле с именем data.json
.
import json
import csv
with open("data.json") as file:
data = json.load(file)
with open("data.csv", "w") as file:
csv_file = csv.writer(file)
for item in data:
csv_file.writerow([item['pk'], item['model']] + item['fields'].values())
csv_file.writerow
(нет f.writerow
, конечно, я предполагаю, что вы сделали там опечатку!) Хочет последовательность, а не dict, и в вашем примере каждый элемент является dict. Это будет работать для ДРУГОГО частного случая, как я определил в своем ответе, - где в файле JSON имеется массив массивов; он не работает для массива объектов, который является особым случаем, который вы пытаетесь решить (для этого требуется csv.DictWriter
- и, конечно же, вам нужно извлечь имена полей и принять решение о заказе в порядке для его создания! -).
– Alex Martelli
9 December 2009 в 05:54
К сожалению, у меня нет репутации enouthg, чтобы внести небольшой вклад в удивительный ответ @Alec McGail. Я использовал Python3, и мне нужно было преобразовать карту в список, следующий за комментарием @Alexis R.
Дополнительная информация Я нашел, что csv-writer добавлял дополнительный CR в файл (у меня есть пустая строка для каждой строки с данными внутри файла csv). Решение было очень легко после ответа @Jason R. Coombs на этот поток: CSV в Python, добавив дополнительный возврат каретки
Вам нужно просто добавить lineterminator = '\n 'для csv.writer. Это будет: csv_w = csv.writer( out_file, lineterminator='\n' )
Как упоминалось в предыдущих ответах, трудность преобразования json в csv заключается в том, что json-файл может содержать вложенные словари и, следовательно, быть многомерной структурой данных, а csv представляет собой структуру данных 2D. Однако хороший способ превратить многомерную структуру в csv состоит в том, чтобы иметь несколько csvs, которые объединяются с первичными ключами.
В вашем примере первый вывод csv имеет столбцы «pk», «model», , "поля" в качестве столбцов. Значения для «pk» и «model» легко получить, но поскольку столбец «поля» содержит словарь, он должен быть его собственным csv, и поскольку «кодовое имя» появляется как первичный ключ, вы можете использовать его как вход для «полей» для завершения первого сеанса. Второй csv содержит словарь из столбца «поля» с кодовым именем в качестве первичного ключа, который можно использовать для связывания двух csvs вместе.
Вот решение для вашего json-файла, который преобразует вложенные словари до 2 csvs.
import csv
import json
def readAndWrite(inputFileName, primaryKey=""):
input = open(inputFileName+".json")
data = json.load(input)
input.close()
header = set()
if primaryKey != "":
outputFileName = inputFileName+"-"+primaryKey
if inputFileName == "data":
for i in data:
for j in i["fields"].keys():
if j not in header:
header.add(j)
else:
outputFileName = inputFileName
for i in data:
for j in i.keys():
if j not in header:
header.add(j)
with open(outputFileName+".csv", 'wb') as output_file:
fieldnames = list(header)
writer = csv.DictWriter(output_file, fieldnames, delimiter=',', quotechar='"')
writer.writeheader()
for x in data:
row_value = {}
if primaryKey == "":
for y in x.keys():
yValue = x.get(y)
if type(yValue) == int or type(yValue) == bool or type(yValue) == float or type(yValue) == list:
row_value[y] = str(yValue).encode('utf8')
elif type(yValue) != dict:
row_value[y] = yValue.encode('utf8')
else:
if inputFileName == "data":
row_value[y] = yValue["codename"].encode('utf8')
readAndWrite(inputFileName, primaryKey="codename")
writer.writerow(row_value)
elif primaryKey == "codename":
for y in x["fields"].keys():
yValue = x["fields"].get(y)
if type(yValue) == int or type(yValue) == bool or type(yValue) == float or type(yValue) == list:
row_value[y] = str(yValue).encode('utf8')
elif type(yValue) != dict:
row_value[y] = yValue.encode('utf8')
writer.writerow(row_value)
readAndWrite("data")
Мой простой способ решить эту проблему:
Создайте новый файл Python, например: json_to_csv.py
Добавьте этот код:
import csv, json, sys
#if you are not using utf-8 files, remove the next line
sys.setdefaultencoding("UTF-8")
#check if you pass the input file and output file
if sys.argv[1] is not None and sys.argv[2] is not None:
fileInput = sys.argv[1]
fileOutput = sys.argv[2]
inputFile = open(fileInput)
outputFile = open(fileOutput, 'w')
data = json.load(inputFile)
inputFile.close()
output = csv.writer(outputFile)
output.writerow(data[0].keys()) # header row
for row in data:
output.writerow(row.values())
После добавления этот код, сохраните файл и запустите на терминале:
python json_to_csv.py input.txt output.csv
blockquote>Надеюсь, это поможет вам.
SEEYA!
Это работает относительно хорошо. Он выравнивает json, чтобы записать его в файл csv. Вложенные элементы управляются:)
Это для python 3
import json
o = json.loads('your json string') # Be careful, o must be a list, each of its objects will make a line of the csv.
def flatten(o, k='/'):
global l, c_line
if isinstance(o, dict):
for key, value in o.items():
flatten(value, k + '/' + key)
elif isinstance(o, list):
for ov in o:
flatten(ov, '')
elif isinstance(o, str):
o = o.replace('\r',' ').replace('\n',' ').replace(';', ',')
if not k in l:
l[k]={}
l[k][c_line]=o
def render_csv(l):
ftime = True
for i in range(100): #len(l[list(l.keys())[0]])
for k in l:
if ftime :
print('%s;' % k, end='')
continue
v = l[k]
try:
print('%s;' % v[i], end='')
except:
print(';', end='')
print()
ftime = False
i = 0
def json_to_csv(object_list):
global l, c_line
l = {}
c_line = 0
for ov in object_list : # Assumes json is a list of objects
flatten(ov)
c_line += 1
render_csv(l)
json_to_csv(o)
.
Я не уверен, что этот вопрос решен уже или нет, но позвольте мне вставить то, что я сделал для справки.
Во-первых, ваш JSON имеет вложенные объекты, поэтому он обычно не может быть напрямую преобразован в CSV , Вы должны изменить это на что-то вроде этого:
{
"pk": 22,
"model": "auth.permission",
"codename": "add_logentry",
"content_type": 8,
"name": "Can add log entry"
},
......]
Вот мой код для генерации CSV из этого:
import csv
import json
x = """[
{
"pk": 22,
"model": "auth.permission",
"fields": {
"codename": "add_logentry",
"name": "Can add log entry",
"content_type": 8
}
},
{
"pk": 23,
"model": "auth.permission",
"fields": {
"codename": "change_logentry",
"name": "Can change log entry",
"content_type": 8
}
},
{
"pk": 24,
"model": "auth.permission",
"fields": {
"codename": "delete_logentry",
"name": "Can delete log entry",
"content_type": 8
}
}
]"""
x = json.loads(x)
f = csv.writer(open("test.csv", "wb+"))
# Write CSV Header, If you dont need that, remove this line
f.writerow(["pk", "model", "codename", "name", "content_type"])
for x in x:
f.writerow([x["pk"],
x["model"],
x["fields"]["codename"],
x["fields"]["name"],
x["fields"]["content_type"]])
Вы получите вывод как:
pk,model,codename,name,content_type
22,auth.permission,add_logentry,Can add log entry,8
23,auth.permission,change_logentry,Can change log entry,8
24,auth.permission,delete_logentry,Can delete log entry,8
[u'
и ']
. Что такое (после обработки) обходной путь? если есть один ... :)
– Dror
10 July 2014 в 13:20
TypeError: a bytes-like object is required, not 'str'
на f.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
– Aditya Hariharan
7 March 2017 в 10:31
Общее решение, которое переводит любой json-список объектов flat в csv.
Передайте файл input.json в качестве первого аргумента в командной строке.
import csv, json, sys
input = open(sys.argv[1])
data = json.load(input)
input.close()
output = csv.writer(sys.stdout)
output.writerow(data[0].keys()) # header row
for row in data:
output.writerow(row.values())
Будет легко использовать csv.DictWriter()
, подробная реализация может быть такой:
def read_json(filename):
return json.loads(open(filename).read())
def write_csv(data,filename):
with open(filename) as outf:
writer = csv.DictWriter(outf, data[0].keys())
writer.writeheader()
for row in data:
writer.writerow(row)
# implement
write_csv(read_json('test.json'), 'output.csv')
Обратите внимание, что это предполагает, что все ваши объекты JSON имеют одинаковые поля.
Это не очень умный способ сделать это, но у меня была та же проблема, и это сработало для меня:
import csv
f = open('data.json')
data = json.load(f)
f.close()
new_data = []
for i in data:
flat = {}
names = i.keys()
for n in names:
try:
if len(i[n].keys()) > 0:
for ii in i[n].keys():
flat[n+"_"+ii] = i[n][ii]
except:
flat[n] = i[n]
new_data.append(flat)
f = open(filename, "r")
writer = csv.DictWriter(f, new_data[0].keys())
writer.writeheader()
for row in new_data:
writer.writerow(row)
f.close()
Поскольку данные, как представляется, находятся в формате словаря, кажется, что вы действительно должны использовать csv.DictWriter () для фактического вывода строк с соответствующей информацией заголовка. Это должно позволить упростить обработку. Параметр fieldnames затем правильно настроил порядок, в то время как вывод первой строки, поскольку заголовки позволили бы его читать и обрабатывать позже csv.DictReader ().
Например, Майк Рефас использовал
output = csv.writer(sys.stdout)
output.writerow(data[0].keys()) # header row
for row in data:
output.writerow(row.values())
Однако просто измените начальную настройку на output = csv.DictWriter (наборы файлов, fieldnames = data [0] .keys ())
Обратите внимание, что поскольку порядок элементов в словарь не определен, вам, возможно, придется явно создавать записи полей. Как только вы это сделаете, писатель будет работать. Затем записи записываются так, как показано на рисунке.
Модифицированный ответ Алека Макгейла для поддержки JSON со списками внутри
def flattenjson(self, mp, delim="|"):
ret = []
if isinstance(mp, dict):
for k in mp.keys():
csvs = self.flattenjson(mp[k], delim)
for csv in csvs:
ret.append(k + delim + csv)
elif isinstance(mp, list):
for k in mp:
csvs = self.flattenjson(k, delim)
for csv in csvs:
ret.append(csv)
else:
ret.append(mp)
return ret
Спасибо!
С библиотекой pandas
это так же просто, как использование двух команд!
pandas.read_json()
Чтобы преобразовать строку JSON в объект pandas (либо серию, либо dataframe). Затем, если предположить, что результаты были сохранены как df
:
df.to_csv()
, которые могут либо возвращать строку, либо записывать непосредственно в csv-файл.
На основании многословия предыдущего ответы, мы все должны благодарить панды за ярлык.
Я знаю, что прошло много времени с тех пор, как этот вопрос был задан, но я подумал, что могу добавить к каждому другому ответу и опубликовать сообщение в блоге, которое, по-моему, объясняет решение в краткой форме.
employ_data = open('/tmp/EmployData.csv', 'w')
csvwriter = csv.writer(employ_data)
count = 0
for emp in emp_data:
if count == 0:
header = emp.keys()
csvwriter.writerow(header)
count += 1
csvwriter.writerow(emp.values())
employ_data.close()