Як можна конвертувати 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/…
Micah Elliott

Альтернатива третьої сторони: json-csv.com (для разових перетворень) або json-csv.com/api для автоматизації з Python. Це просте рішення для більш складних структур JSON.
Стек чоловік

Відповіді:


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), а а - деякий змінний, про який я заявляю перед
дяком

Для мене це працює майже ідеально. У експортованому 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

118

З pandas бібліотекою , це так само просто , як з допомогою двох команд!

pandas.read_json()

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

df.to_csv()

Який може повернути рядок або записати безпосередньо у файл csv.

Виходячи з багатослів’я попередніх відповідей, ми всі повинні дякувати пандам за ярлик.


1
Це фантастична відповідь (+1) - така проста і .to_csv()дуже потужна (наприклад, фільтрування стовпців безкоштовно). Мені потрібно вивчити панди.
WoJ

3
Як вказувалося, ця відповідь не працює для даних цього питання. orient='records'Потрібно встановити, але кожен рядок fieldsбуде як і раніше dict, а це не те, що вимагала ОП.
Trenton McKinney

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
}

Після застосування цієї функції до кожного дикта у вхідному масиві об'єктів 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 (зі струнними клавішами), 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 є "зазубровані" стовпці, тобто скажімо, що рядок1 має 5 стовпців, але рядок2 має 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. TypeError: може лише об'єднати список (не "dict_values") до списку
Аполо Радомер,

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 [' field ']. values ​​()) TypeError: може лише об'єднати список (не "dict_values") до списку
Mian Asbat Ahmad

Спробував це знову лише зараз у 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, яка є двовимірною структурою даних. Однак хороший спосіб перетворити багатовимірну структуру на csv - це мати декілька csvs, які пов'язані разом із первинними ключами.

У вашому прикладі перший вихід csv містить стовпці "pk", "model", "поля" як ваші стовпці. Значення для "pk" та "model" легко отримати, але оскільки стовпець "поля" містить словник, він повинен бути власним csv, а оскільки "кодове ім'я" є первинним ключем, ви можете використовувати як вхідний для "полів", щоб заповнити перший 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

Я знаю, що минуло давно, як це питання було задано, але я подумав, що можу додати відповідь усіх інших і поділитися дописом у блозі, який, на мою думку, пояснюють рішення дуже стисло.

Ось посилання

Відкрийте файл для написання

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

Це не дуже розумний спосіб зробити це, але у мене була така ж проблема, і це працювало для мене:

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. Вкладені елементи керуються :)

Це для 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)

насолоджуватися.


.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

Дивно, але я виявив, що жоден з наведених тут відповідей коректно не стосується всіх можливих сценаріїв (наприклад, вкладених диктів, вкладених списків, жодних значень тощо).

Це рішення має працювати у всіх сценаріях:

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')])

Вищезгаданий код виконаний у локально встановленій піхармі і він успішно перетворив файл json у файл csv. Сподіваюся, що це допоможе перетворити файли.


0

Оскільки дані, як видається, є у словниковому форматі, здається, що ви фактично повинні використовувати csv.DictWriter (), щоб фактично виводити рядки з відповідною інформацією заголовка. Це повинно дозволити обробляти конверсію дещо простіше. Параметр імен поля тоді встановив би порядок належним чином, тоді як вихід першого рядка як заголовки дозволив би його читати та обробляти пізніше csv.DictReader ().

Наприклад, використаний Майк Репас

output = csv.writer(sys.stdout)

output.writerow(data[0].keys())  # header row

for row in data:
  output.writerow(row.values())

Однак просто змініть початкові налаштування на вихід = csv.DictWriter (набір файлів, назви полів = дані [0]. Ключі ())

Зауважте, оскільки порядок елементів у словнику не визначений, можливо, вам доведеться явно створювати записи полів. Після цього записування спрацює. Потім записи працюють як показано спочатку.


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, а потім зберігаю його у файл 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.