Json to CSV python [дубликат]

Вы можете попробовать это.

    >>> 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'
122
задан martineau 27 September 2016 в 11:46
поделиться

17 ответов

Я предполагаю, что ваш 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 ) )

Надеюсь, это поможет!

67
ответ дан Alec McGail 20 August 2018 в 07:51
поделиться
  • 1
    это писатель, а не write_row – philgo20 2 September 2016 в 19:51
  • 2
    @ philgo20 спасибо за определение, отредактированный – Alec McGail 2 September 2016 в 20:10
  • 3
    @AlecMcGail не работает с python 3.x – EmptyData 14 April 2017 в 08:03
  • 4
    @EmptyData Я предполагаю, что вы имеете в виду «карту». и "уменьшить" частей. как насчет столбцов = список (установить (x для y в входе для x в y.keys ())) " – Alec McGail 15 April 2017 в 15:24
  • 5
    Используя Python 3.6, мне пришлось составить список сплющенных JSON, чтобы получить последний цикл: «input = list (map (lambda x: flattenjson (x,« __ »), input))». Я не понимаю, почему iterable недостаточно. Я также должен был указать кодировку при открытии выходного файла, так как мои данные используют UTF8. Это определенно помогло, спасибо! – Alexis R 1 February 2018 в 11:10

JSON может представлять собой широкий спектр структур данных - объект JS «примерно похож на Python dict (со строковыми ключами), JS« массив », примерно как список Python, и вы можете вложить их до тех пор, пока конечные «листовые» элементы - это числа или строки.

CSV может по существу представлять только двухмерную таблицу - необязательно с первой строкой «заголовков», то есть «имена столбцов», которые могут таблица, интерпретируемая как список dicts, вместо обычной интерпретации, список списков (опять же, «листовые» элементы могут быть числами или строками).

Итак, в общем случае вы можете ' t переводит произвольную структуру JSON в CSV. В нескольких особых случаях вы можете (массив массивов без дальнейшего вложения, массивы объектов, все из которых имеют одинаковые ключи). Какой особый случай, если таковой имеется, относится к вашей проблеме? Детали решения зависят от того, какой особый случай у вас есть. Учитывая удивительный факт, что вы даже не упоминаете, какой из них применим, я подозреваю, что вы, возможно, не считали ограничение, ни одно из применимых случаев на самом деле не применяется, и ваша проблема невозможна. Но проясните!

33
ответ дан Alex Martelli 20 August 2018 в 07:51
поделиться

У меня возникли проблемы с предложенным решением Дэна , но это сработало для меня:

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 } }
]
5
ответ дан Community 20 August 2018 в 07:51
поделиться
  • 1
    Получена ошибка при попытке вашей программы по вашим данным образца. C: \ curl & gt; python json2csv.py. Traceback (последний последний вызов): File & quot; json2csv.py & quot ;, строка 11, в & lt; module & gt; f.writerow ([item ['pk'], item ['model']] + item ['fields']. values ​​()) TypeError: может только конкатенировать список (not & quot; dict_values ​​& quot;) в список – Mian Asbat Ahmad 10 December 2015 в 12:54
  • 2
    Попробовал это снова сейчас в Python 2.7.9, и он отлично работает для меня. – Amanda 10 December 2015 в 20:33

Этот код должен работать на вас, предполагая, что ваши данные 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())
20
ответ дан Dan Loewenherz 20 August 2018 в 07:51
поделиться
  • 1
    Hmmm, no - csv_file.writerow (нет f.writerow, конечно, я предполагаю, что вы сделали там опечатку!) Хочет последовательность, а не dict, и в вашем примере каждый элемент является dict. Это будет работать для ДРУГОГО частного случая, как я определил в своем ответе, - где в файле JSON имеется массив массивов; он не работает для массива объектов, который является особым случаем, который вы пытаетесь решить (для этого требуется csv.DictWriter - и, конечно же, вам нужно извлечь имена полей и принять решение о заказе в порядке для его создания! -). – Alex Martelli 9 December 2009 в 05:54
  • 2
    Ой, опечатка. Спасибо, что поймал это. – Dan Loewenherz 9 December 2009 в 06:55

К сожалению, у меня нет репутации 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' )

0
ответ дан derwyddon 20 August 2018 в 07:51
поделиться

Как упоминалось в предыдущих ответах, трудность преобразования 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")
4
ответ дан dmathewwws 20 August 2018 в 07:51
поделиться

Мой простой способ решить эту проблему:

Создайте новый файл 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

Надеюсь, это поможет вам.

SEEYA!

2
ответ дан Gabriel Pires 20 August 2018 в 07:51
поделиться
  • 1
    Этот образец работает как шарм! спасибо за обмен, я смог преобразовать свой json-файл в CSV, используя этот скрипт python – Mostafa 23 October 2017 в 16:52

Это работает относительно хорошо. Он выравнивает 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)

.

2
ответ дан Loïc 20 August 2018 в 07:51
поделиться

Я не уверен, что этот вопрос решен уже или нет, но позвольте мне вставить то, что я сделал для справки.

Во-первых, ваш 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
87
ответ дан martineau 20 August 2018 в 07:51
поделиться
  • 1
    это работа, но жаль, прежде чем я могу получить что-то, что не сложно. Я думаю, что лучше, я могу использовать f.writerow (a), а a - некоторый variabel, который я объявляю раньше, чем спасибо – little_fish 9 December 2009 в 09:16
  • 2
    Для меня это работает почти отлично. В экспортированном CSV некоторые поля окружены [u' и ']. Что такое (после обработки) обходной путь? если есть один ... :) – Dror 10 July 2014 в 13:20
  • 3
    Ниже я показал способ сделать это в более общем плане, без необходимости его жесткого кодирования – Alec McGail 26 August 2015 в 21:11
  • 4
    @AlecMcGail, хорошая работа, сделал +1 – YOU 27 August 2015 в 02:14
  • 5
    эй, я пробовал это, но я получаю 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())
25
ответ дан Mike Repass 20 August 2018 в 07:51
поделиться
  • 1
    Важный комментарий - этот код вводит столбцы / заголовки из полей в первой строке. Если ваши json-данные имеют «зубчатые» столбцы, то есть позволяют говорить, что row1 имеет 5 столбцов, но row2 имеет 6 столбцов, тогда вам нужно сделать первый проход по данным, чтобы получить общий набор всех столбцов и использовать их в качестве заголовков. – Mike Repass 7 December 2012 в 23:59
  • 2
    С данными, которые у меня были, это была большая часть необходимого мне решения, так как мой JSON не был зазубрен, он отлично работал с некоторыми небольшими корректировками для вывода, поскольку я запускал это в существующем скрипте. – MichaelF 24 April 2014 в 16:00
  • 3
    Этот код также предполагает, что значения будут выводиться в том же порядке, что и ключи в строке заголовка. Хотя это, возможно, сработало удачей, это отнюдь не гарантировано. – RyanHennig 28 July 2015 в 19:09
  • 4
    Получение ошибки кодирования. Любая идея, как добавить кодировку в utf-8? – Elad Tabak 7 April 2016 в 09:34

Будет легко использовать 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 имеют одинаковые поля.

Вот ссылка , которая может вам помочь.

12
ответ дан ReturnHttp402 20 August 2018 в 07:51
поделиться
  • 1
    Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - Из обзора – purplepsycho 1 December 2016 в 11:04
  • 2
    Thx для вашего предложения. – ReturnHttp402 2 December 2016 в 06:07
  • 3
    @purplepsycho Я нашел этот ответ с downvote, который был заслужен только для ссылки. Новый пользователь, который, возможно, не знал, что ссылка только не является хорошим ответом, исправил это. Я поддержал; возможно, вы тоже могли бы побудить нового пользователя продолжать участвовать в нашем сообществе? – Mawg 19 January 2017 в 09:40

Это не очень умный способ сделать это, но у меня была та же проблема, и это сработало для меня:

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()
1
ответ дан rmNyro 20 August 2018 в 07:51
поделиться

Поскольку данные, как представляется, находятся в формате словаря, кажется, что вы действительно должны использовать 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 ())

Обратите внимание, что поскольку порядок элементов в словарь не определен, вам, возможно, придется явно создавать записи полей. Как только вы это сделаете, писатель будет работать. Затем записи записываются так, как показано на рисунке.

0
ответ дан sabbahillel 20 August 2018 в 07:51
поделиться

Модифицированный ответ Алека Макгейла для поддержки 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

Спасибо!

1
ответ дан Sawan Vaidya 20 August 2018 в 07:51
поделиться

С библиотекой pandas это так же просто, как использование двух команд!

pandas.read_json()

Чтобы преобразовать строку JSON в объект pandas (либо серию, либо dataframe). Затем, если предположить, что результаты были сохранены как df:

df.to_csv()

, которые могут либо возвращать строку, либо записывать непосредственно в csv-файл.

На основании многословия предыдущего ответы, мы все должны благодарить панды за ярлык.

38
ответ дан vmg 20 August 2018 в 07:51
поделиться

Я знаю, что прошло много времени с тех пор, как этот вопрос был задан, но я подумал, что могу добавить к каждому другому ответу и опубликовать сообщение в блоге, которое, по-моему, объясняет решение в краткой форме.

Вот ссылка

Откройте файл для записи

employ_data = open('/tmp/EmployData.csv', 'w')

Создайте объект записи csv

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()
3
ответ дан whale_steward 20 August 2018 в 07:51
поделиться
0
ответ дан Max Berman 31 October 2018 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: