Как я могу конвертировать JSON в CSV?


184

У меня есть файл JSON, который я хочу преобразовать в файл CSV. Как я могу сделать это с Python?

Я попытался:

import json
import csv

f = open('data.json')
data = json.load(f)
f.close()

f = open('data.csv')
csv_file = csv.writer(f)
for item in data:
    csv_file.writerow(item)

f.close()

Однако это не сработало. Я использую Django, и я получил ошибку:

file' object has no attribute 'writerow'

Затем я попробовал следующее:

import json
import csv

f = open('data.json')
data = json.load(f)
f.close()

f = open('data.csv')
csv_file = csv.writer(f)
for item in data:
    f.writerow(item)  # ← changed

f.close()

Я тогда получаю ошибку:

sequence expected

Пример файла 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
        }
    }, {
        "pk": 4,
        "model": "auth.permission",
        "fields": {
            "codename": "add_group",
            "name": "Can add group",
            "content_type": 2
        }
    }, {
        "pk": 10,
        "model": "auth.permission",
        "fields": {
            "codename": "add_message",
            "name": "Can add message",
            "content_type": 4
        }
    }
]

1
csv_file.writerow (item) требует, чтобы элемент был простым списком строк или чисел. Попробуйте преобразовать каждый объект json в плоский список, как {"pk": 22, "model": "auth.permission"} станет [22, auth.permission].
Подавление

1
Простой подход к этому заключается в использовании jq, как описано здесь: stackoverflow.com/questions/32960857/…
Мика Эллиотт,

Альтернатива стороннего производителя: json-csv.com (для одноразовых преобразований) или json-csv.com/api для автоматизации с помощью Python. Это простое решение для более сложных структур JSON.
Stack Man

Ответы:


129

Во-первых, ваш 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

2
это работа, но извините, прежде чем я могу получить что-то, что не является жестким кодом, я думаю, что лучше я могу использовать f.writerow (a), а a - это некоторая переменная, которую я объявляю раньше, спасибо
little_fish

Для меня это работает почти идеально. В экспортированном CSV некоторые поля окружены [u'и ']. Какой обходной путь (без постобработки)? если есть один ... :)
Дрор

3
Ниже я показал способ сделать это в более общем смысле, не прибегая к жесткому кодированию
Алек МакГейл,

4
эй, я пробовал это, но я получаю TypeError: a bytes-like object is required, not 'str'наf.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Адитья Харихарана

8
для python3 измените строку с открытием CSV-файла наf = csv.writer(open("test.csv", "w", newline=''))
PiotrK

119

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

pandas.read_json()

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

df.to_csv()

Который может либо вернуть строку, либо записать напрямую в csv-файл.

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


1
Это фантастический ответ (+1) - такой простой и .to_csv()действительно мощный (например, бесплатная фильтрация столбцов). Мне нужно выучить панд.
WoJ

3
Как указано, этот ответ не работает для данных в этом вопросе. orient='records'должен быть установлен, но каждая строка fieldsвсе равно будет a dict, что не является запрошенным OP.
Трентон МакКинни

90

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

является

{
    "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 ) )

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


Используя Python 3.6, мне пришлось составить список сплющенного JSON, чтобы заставить работать последний цикл: "input = list (map (lambda x: flattenjson (x," __ "), input))". Я не понимаю, почему итерируемого недостаточно. Я также должен был указать кодировку при открытии выходного файла, так как мои данные используют UTF8. Это определенно помогло, спасибо!
Alexis R

Это здорово, спасибо Алек! Я изменил его для работы с несколькими уровнями вложенности: stackoverflow.com/a/57228641/473201
phreakhead

35

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

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

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


31

Универсальное решение, которое переводит любой список плоских объектов json в 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())

2
Важный комментарий - этот код выводит столбцы / заголовки из полей в самой первой строке. Если ваши данные json имеют «неровные» столбцы, т. Е. Предположим, что row1 имеет 5 столбцов, а row2 имеет 6 столбцов, то вам необходимо выполнить первый проход по данным, чтобы получить общий набор всех столбцов и использовать его в качестве заголовков.
Майк Репасс

С данными, которые у меня были, это была большая часть решения, в котором я нуждался, поскольку мой JSON не был зазубренным, он прекрасно работал с некоторыми небольшими изменениями для вывода, так как я выполнял это в существующем сценарии.
MichaelF

1
Этот код также предполагает, что значения будут выводиться в том же порядке, что и ключи в строке заголовка. Хотя это, возможно, сработало удачей, это ни в коем случае не гарантировано.
RyanHennig

Получение ошибки кодирования. Есть идеи, как добавить кодировку в utf-8?
Элад Табак

25

Этот код должен работать для вас, предполагая, что ваши данные 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:
        fields = list(item['fields'].values())
        csv_file.writerow([item['pk'], item['model']] + fields)

1
Хммм, нет - csv_file.writerow(нет, f.writerowконечно, я предполагаю, что вы сделали опечатку там!) Хочет последовательность, а не диктат - и в вашем примере каждый элемент является диктатом. Это будет работать для ДРУГОГО особого случая, как я определил в своем ответе - где файл JSON имеет массив массивов; он не работает для массива объектов, что является особым случаем, который вы пытаетесь решить (для этого требуется csv.DictWriter- и, конечно, вам нужно извлечь имена полей и выбрать порядок, чтобы создать его экземпляр ! -).
Алекс Мартелли

@DanLoewenherz Это не работает в последних версиях Python. Ошибка типа: можно только объединить список (но не «dict_values») в список
Apolo Radomer,

18

Это будет легко использовать csv.DictWriter(), подробная реализация может быть такой:

def read_json(filename):
    return json.loads(open(filename).read())
def write_csv(data,filename):
    with open(filename, 'w+') 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 имеют одинаковые поля.

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


Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. - Из Обзора
Матье

3
@purplepsycho Я нашел этот ответ с понижением голоса, которое заслуживало только ссылки. Новый пользователь, который, возможно, не знал, что только ссылка не является хорошим ответом, исправил это. Я проголосовал; возможно, вы тоже могли бы призвать нового пользователя продолжать участвовать в нашем сообществе?
Мауг говорит восстановить Монику

6

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

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

Произошла ошибка при попытке вашей программы использовать данные примера C: \ curl> python json2csv.py Traceback (последний вызов был последним): файл "json2csv.py", строка 11, в <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. values ​​()) TypeError: можно только объединить список (не "dict_values") в список
Миан Асбат Ахмад

Попробовал еще раз только сейчас в Python 2.7.9, и он прекрасно работает для меня.
Аманда

6

Используйте json_normalizeот pandas:

  • Учитывая предоставленные данные, в файле с именем test.json
  • encoding='utf-8' может не быть необходимым.
  • Следующий код использует pathlibбиблиотеку
    • .open это метод pathlib
    • Работает и с не-Windows путями
import pandas as pd
# As of Pandas 1.01, json_normalize as pandas.io.json.json_normalize is deprecated and is now exposed in the top-level namespace.
# from pandas.io.json import json_normalize
from pathlib import Path
import json

# set path to file
p = Path(r'c:\some_path_to_file\test.json')

# read json
with p.open('r', encoding='utf-8') as f:
    data = json.loads(f.read())

# create dataframe
df = pd.json_normalize(data)

# dataframe view
 pk            model  fields.codename           fields.name  fields.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
  4  auth.permission        add_group         Can add group                    2
 10  auth.permission      add_message       Can add message                    4

# save to csv
df.to_csv('test.csv', index=False, encoding='utf-8')

Выход CSV:

pk,model,fields.codename,fields.name,fields.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
4,auth.permission,add_group,Can add group,2
10,auth.permission,add_message,Can add message,4

Другие ресурсы для более сильно вложенных объектов JSON:


4

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

В вашем примере первый вывод csv содержит столбцы «pk», «model», «fields» в качестве столбцов. Значения для «pk» и «model» легко получить, но поскольку столбец «fields» содержит словарь, он должен быть собственным csv, а поскольку «codename» является первичным ключом, его можно использовать в качестве входных данных. для "полей", чтобы завершить первый CSV. Второй CSV содержит словарь из столбца «fields» с кодовым именем в качестве первичного ключа, который можно использовать для связывания двух CSV.

Вот решение для вашего файла JSON, который преобразует вложенные словари в 2 CSV.

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

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

Вот ссылка

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

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

Создайте объект csv writer

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

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

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

3

Ответ Алека великолепен, но он не работает в случае, когда есть несколько уровней вложенности. Вот модифицированная версия, которая поддерживает несколько уровней вложенности. Это также делает имена заголовков более привлекательными, если вложенный объект уже указывает свой собственный ключ (например, данные Firebase Analytics / BigTable / BigQuery):

"""Converts JSON with nested fields into a flattened CSV file.
"""

import sys
import json
import csv
import os

import jsonlines

from orderedset import OrderedSet

# from https://stackoverflow.com/a/28246154/473201
def flattenjson( b, prefix='', delim='/', val=None ):
  if val == None:
    val = {}

  if isinstance( b, dict ):
    for j in b.keys():
      flattenjson(b[j], prefix + delim + j, delim, val)
  elif isinstance( b, list ):
    get = b
    for j in range(len(get)):
      key = str(j)

      # If the nested data contains its own key, use that as the header instead.
      if isinstance( get[j], dict ):
        if 'key' in get[j]:
          key = get[j]['key']

      flattenjson(get[j], prefix + delim + key, delim, val)
  else:
    val[prefix] = b

  return val

def main(argv):
  if len(argv) < 2:
    raise Error('Please specify a JSON file to parse')

  filename = argv[1]
  allRows = []
  fieldnames = OrderedSet()
  with jsonlines.open(filename) as reader:
    for obj in reader:
      #print obj
      flattened = flattenjson(obj)
      #print 'keys: %s' % flattened.keys()
      fieldnames.update(flattened.keys())
      allRows.append(flattened)

  outfilename = filename + '.csv'
  with open(outfilename, 'w') as file:
    csvwriter = csv.DictWriter(file, fieldnames=fieldnames)
    csvwriter.writeheader()
    for obj in allRows:
      csvwriter.writerow(obj)



if __name__ == '__main__':
  main(sys.argv)

2

Это работает относительно хорошо. Это выравнивает JSON, чтобы записать его в CSV-файл. Вложенные элементы управляются :)

Это для питона 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)

наслаждаться.


CSV-файл не был сгенерирован, вместо этого текст CSV был выведен на консоль. Кроме того, json.loadsне работал, я заставил его работать json.load, что приятно выдает объект списка. В-третьих, вложенные элементы были потеряны.
ZygD

2

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

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

Я надеюсь, что это поможет вам.

ДО ВСТРЕЧИ!


1
Этот образец работает как шарм! спасибо, что поделились, я смог преобразовать мой файл JSON в CSV с помощью этого сценария Python
Mostafa

2

Удивительно, но я обнаружил, что ни один из ответов, опубликованных здесь, до сих пор правильно не рассматривал все возможные сценарии (например, вложенные символы, вложенные списки, значения None и т. Д.).

Это решение должно работать во всех сценариях:

def flatten_json(json):
    def process_value(keys, value, flattened):
        if isinstance(value, dict):
            for key in value.keys():
                process_value(keys + [key], value[key], flattened)
        elif isinstance(value, list):
            for idx, v in enumerate(value):
                process_value(keys + [str(idx)], v, flattened)
        else:
            flattened['__'.join(keys)] = value

    flattened = {}
    for key in json.keys():
        process_value([key], json[key], flattened)
    return flattened

2

Попробуй это

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 item in data:
    output.writerow(item.values())

2

Этот код работает для любого файла JSON

# -*- coding: utf-8 -*-
"""
Created on Mon Jun 17 20:35:35 2019
author: Ram
"""

import json
import csv

with open("file1.json") as file:
    data = json.load(file)



# create the csv writer object
pt_data1 = open('pt_data1.csv', 'w')
csvwriter = csv.writer(pt_data1)

count = 0

for pt in data:

      if count == 0:

             header = pt.keys()

             csvwriter.writerow(header)

             count += 1

      csvwriter.writerow(pt.values())

pt_data1.close()

1

Изменен ответ Алек МакГейл для поддержки 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
import json,csv
t=''
t=(type('a'))
json_data = []
data = None
write_header = True
item_keys = []
try:
with open('kk.json') as json_file:
    json_data = json_file.read()

    data = json.loads(json_data)
except Exception as e:
    print( e)

with open('bar.csv', 'at') as csv_file:
    writer = csv.writer(csv_file)#, quoting=csv.QUOTE_MINIMAL)
    for item in data:
        item_values = []
        for key in item:
            if write_header:
                item_keys.append(key)
            value = item.get(key, '')
            if (type(value)==t):
                item_values.append(value.encode('utf-8'))
            else:
                item_values.append(value)
        if write_header:
            writer.writerow(item_keys)
            write_header = False
        writer.writerow(item_values)

1

Если мы рассмотрим приведенный ниже пример преобразования файла формата json в файл в формате csv.

{
 "item_data" : [
      {
        "item": "10023456",
        "class": "100",
        "subclass": "123"
      }
      ]
}

Приведенный ниже код преобразует файл json (data3.json) в файл csv (data3.csv).

import json
import csv
with open("/Users/Desktop/json/data3.json") as file:
    data = json.load(file)
    file.close()
    print(data)

fname = "/Users/Desktop/json/data3.csv"

with open(fname, "w", newline='') as file:
    csv_file = csv.writer(file)
    csv_file.writerow(['dept',
                       'class',
                       'subclass'])
    for item in data["item_data"]:
         csv_file.writerow([item.get('item_data').get('dept'),
                            item.get('item_data').get('class'),
                            item.get('item_data').get('subclass')])

Вышеупомянутый код был выполнен в локально установленном pycharm, и он успешно преобразовал файл json в файл csv. Надеюсь, что это поможет конвертировать файлы.


0

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

К сожалению, у меня нет репутации, чтобы внести небольшой вклад в удивительный ответ @Alec McGail. Я использовал Python3, и мне нужно было преобразовать карту в список после комментария @Alexis R.

Кроме того, я обнаружил, что писатель CSV добавляет дополнительный CR в файл (у меня есть пустая строка для каждой строки с данными внутри файла CSV). Решение было очень простым после ответа @Jason R. Coombs на эту тему: CSV в Python добавляет дополнительный возврат каретки

Вам просто нужно добавить параметр lineterminator = '\ n' в csv.writer. Это будет:csv_w = csv.writer( out_file, lineterminator='\n' )


0

Вы можете использовать этот код для преобразования json-файла в csv-файл. После прочтения файла я конвертирую объект в pandas dataframe, а затем сохраняю его в CSV-файл.

import os
import pandas as pd
import json
import numpy as np

data = []
os.chdir('D:\\Your_directory\\folder')
with open('file_name.json', encoding="utf8") as data_file:    
     for line in data_file:
        data.append(json.loads(line))

dataframe = pd.DataFrame(data)        
## Saving the dataframe to a csv file
dataframe.to_csv("filename.csv", encoding='utf-8',index= False)

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

0

Возможно, я опоздал на вечеринку, но, думаю, я справился с подобной проблемой. У меня был файл JSON, который выглядел так

Структура файла JSON

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

    """json_to_csv.py
    This script reads n numbers of json files present in a folder and then extract certain data from each file and write in a csv file.
    The folder contains the python script i.e. json_to_csv.py, output.csv and another folder descriptions containing all the json files.
"""

import os
import json
import csv


def get_list_of_json_files():
    """Returns the list of filenames of all the Json files present in the folder
    Parameter
    ---------
    directory : str
        'descriptions' in this case
    Returns
    -------
    list_of_files: list
        List of the filenames of all the json files
    """

    list_of_files = os.listdir('descriptions')  # creates list of all the files in the folder

    return list_of_files


def create_list_from_json(jsonfile):
    """Returns a list of the extracted items from json file in the same order we need it.
    Parameter
    _________
    jsonfile : json
        The json file containing the data
    Returns
    -------
    one_sample_list : list
        The list of the extracted items needed for the final csv
    """

    with open(jsonfile) as f:
        data = json.load(f)

    data_list = []  # create an empty list

    # append the items to the list in the same order.
    data_list.append(data['_id'])
    data_list.append(data['_modelType'])
    data_list.append(data['creator']['_id'])
    data_list.append(data['creator']['name'])
    data_list.append(data['dataset']['_accessLevel'])
    data_list.append(data['dataset']['_id'])
    data_list.append(data['dataset']['description'])
    data_list.append(data['dataset']['name'])
    data_list.append(data['meta']['acquisition']['image_type'])
    data_list.append(data['meta']['acquisition']['pixelsX'])
    data_list.append(data['meta']['acquisition']['pixelsY'])
    data_list.append(data['meta']['clinical']['age_approx'])
    data_list.append(data['meta']['clinical']['benign_malignant'])
    data_list.append(data['meta']['clinical']['diagnosis'])
    data_list.append(data['meta']['clinical']['diagnosis_confirm_type'])
    data_list.append(data['meta']['clinical']['melanocytic'])
    data_list.append(data['meta']['clinical']['sex'])
    data_list.append(data['meta']['unstructured']['diagnosis'])
    # In few json files, the race was not there so using KeyError exception to add '' at the place
    try:
        data_list.append(data['meta']['unstructured']['race'])
    except KeyError:
        data_list.append("")  # will add an empty string in case race is not there.
    data_list.append(data['name'])

    return data_list


def write_csv():
    """Creates the desired csv file
    Parameters
    __________
    list_of_files : file
        The list created by get_list_of_json_files() method
    result.csv : csv
        The csv file containing the header only
    Returns
    _______
    result.csv : csv
        The desired csv file
    """

    list_of_files = get_list_of_json_files()
    for file in list_of_files:
        row = create_list_from_json(f'descriptions/{file}')  # create the row to be added to csv for each file (json-file)
        with open('output.csv', 'a') as c:
            writer = csv.writer(c)
            writer.writerow(row)
        c.close()


if __name__ == '__main__':
    write_csv()

Я надеюсь, это поможет. Подробнее о том, как работает этот код, вы можете проверить здесь


0

Это модификация ответа @ MikeRepass. Эта версия записывает CSV в файл и работает как для Python 2, так и для Python 3.

import csv,json
input_file="data.json"
output_file="data.csv"
with open(input_file) as f:
    content=json.load(f)
try:
    context=open(output_file,'w',newline='') # Python 3
except TypeError:
    context=open(output_file,'wb') # Python 2
with context as file:
    writer=csv.writer(file)
    writer.writerow(content[0].keys()) # header row
    for row in content:
        writer.writerow(row.values())
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.