Bagaimana saya bisa mengkonversi JSON ke CSV?

184

Saya memiliki file JSON yang ingin saya konversi menjadi file CSV. Bagaimana saya bisa melakukan ini dengan Python?

Saya mencoba:

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

Namun, itu tidak berhasil. Saya menggunakan Django dan kesalahan yang saya terima adalah:

file' object has no attribute 'writerow'

Saya kemudian mencoba yang berikut:

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

Saya kemudian mendapatkan kesalahan:

sequence expected

Contoh file 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
        }
    }
]
ikan kecil
sumber
1
csv_file.writerow (item) mengharuskan item menjadi daftar string atau angka yang sederhana. Coba konversi setiap objek json menjadi daftar datar, seperti {"pk": 22, "model": "auth.permission"} akan menjadi [22, auth.permission].
Suppressingfire
1
Pendekatan sederhana untuk ini adalah menggunakan jq, seperti dijelaskan di sini: stackoverflow.com/questions/32960857/…
Micah Elliott
Alternatif pihak ketiga: json-csv.com (untuk konversi satu kali) atau json-csv.com/api untuk diotomatisasi dengan Python. Ini adalah solusi sederhana untuk struktur JSON yang lebih kompleks.
Stack Man

Jawaban:

129

Pertama, JSON Anda memiliki objek bersarang, jadi biasanya tidak dapat langsung dikonversi ke CSV. Anda perlu mengubahnya menjadi sesuatu seperti ini:

{
    "pk": 22,
    "model": "auth.permission",
    "codename": "add_logentry",
    "content_type": 8,
    "name": "Can add log entry"
},
......]

Ini kode saya untuk menghasilkan CSV dari itu:

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

Anda akan mendapatkan output sebagai:

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
KAMU
sumber
2
ini bekerja tetapi maaf sebelum saya bisa mendapatkan sesuatu yang tidak sulit kode saya hal itu lebih baik id saya dapat menggunakan f.writerow (a) dan beberapa variabel yang saya nyatakan sebelum terima kasih sebelumnya
little_fish
Bagi saya ini bekerja hampir sempurna. Di CSV yang diekspor, beberapa bidang dikelilingi oleh [u'dan ']. Apa solusinya (non-pasca-pemrosesan)? jika ada satu ... :)
Dror
3
Di bawah ini saya telah menunjukkan cara untuk melakukannya secara lebih umum, tanpa harus melakukan hard-code
Alec McGail
4
hey, saya sudah mencoba ini tapi aku mendapatkan TypeError: a bytes-like object is required, not 'str'dif.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Aditya Hariharan
8
untuk perubahan baris python3 dengan membuka file csv kef = csv.writer(open("test.csv", "w", newline=''))
PiotrK
118

Dengan pandas perpustakaan , ini semudah menggunakan dua perintah!

pandas.read_json()

Untuk mengonversi string JSON ke objek panda (baik seri atau bingkai data). Kemudian, dengan asumsi hasil disimpan sebagai df:

df.to_csv()

Yang dapat mengembalikan string atau menulis langsung ke file csv.

Berdasarkan verbositas dari jawaban sebelumnya, kita semua harus berterima kasih pada panda untuk pintasan.

vmg
sumber
1
Ini adalah jawaban yang fantastis (+1) - sangat sederhana dan .to_csv()sangat kuat (misalnya, pemfilteran kolom gratis). Saya perlu belajar panda.
WoJ
3
Seperti yang ditunjukkan, jawaban ini tidak berfungsi untuk data dalam pertanyaan ini. orient='records'harus ditetapkan, tetapi setiap baris fieldsmasih akan menjadi dict, yang bukan apa yang diminta OP.
Trenton McKinney
90

Saya mengasumsikan bahwa file JSON Anda akan diterjemahkan ke dalam daftar kamus. Pertama kita membutuhkan fungsi yang akan meratakan objek 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

Hasil menjalankan cuplikan ini pada objek JSON Anda:

flattenjson( {
    "pk": 22, 
    "model": "auth.permission", 
    "fields": {
      "codename": "add_message", 
      "name": "Can add message", 
      "content_type": 8
    }
  }, "__" )

adalah

{
    "pk": 22, 
    "model": "auth.permission', 
    "fields__codename": "add_message", 
    "fields__name": "Can add message", 
    "fields__content_type": 8
}

Setelah menerapkan fungsi ini untuk setiap dikt dalam input array objek JSON:

input = map( lambda x: flattenjson( x, "__" ), input )

dan menemukan nama kolom yang relevan:

columns = [ x for row in input for x in row.keys() ]
columns = list( set( columns ) )

tidak sulit menjalankan ini melalui modul 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 ) )

Saya harap ini membantu!

Alec McGail
sumber
Dengan menggunakan Python 3.6, saya harus membuat daftar JSON yang diratakan untuk membuat loop terakhir berfungsi: "input = daftar (peta (lambda x: flattenjson (x," __ "), input))". Saya tidak mengerti mengapa iterable tidak cukup sekalipun. Saya juga harus menentukan pengkodean saat membuka file output karena data saya menggunakan UTF8. Pasti membantu, terima kasih !!
Alexis R
Ini bagus, terima kasih Alec! Saya memodifikasinya agar berfungsi dengan beberapa level sarang: stackoverflow.com/a/57228641/473201
phreakhead
35

JSON dapat mewakili berbagai macam struktur data - "objek" JS kira-kira seperti dict Python (dengan kunci string), JS "array" kira-kira seperti daftar Python, dan Anda dapat membuat sarangnya selama final " elemen daun adalah angka atau string.

CSV pada dasarnya hanya dapat mewakili tabel 2-D - opsional dengan baris pertama "header", yaitu, "nama kolom", yang dapat membuat tabel ditafsirkan sebagai daftar dicts, alih-alih interpretasi normal, daftar daftar (sekali lagi, elemen "daun" bisa berupa angka atau string).

Jadi, dalam kasus umum, Anda tidak dapat menerjemahkan struktur JSON sewenang-wenang ke CSV. Dalam beberapa kasus khusus Anda dapat (array array tanpa bersarang lebih lanjut; array objek yang semuanya memiliki kunci yang persis sama). Kasus khusus mana, jika ada, yang berlaku untuk masalah Anda? Rincian solusi tergantung pada kasus khusus yang Anda miliki. Mengingat fakta yang mencengangkan bahwa Anda bahkan tidak menyebutkan yang mana yang berlaku, saya curiga Anda mungkin tidak mempertimbangkan kendala, tidak ada kasus yang dapat digunakan sebenarnya berlaku, dan masalah Anda tidak mungkin diselesaikan. Tapi tolong lakukan klarifikasi!

Alex Martelli
sumber
31

Solusi umum yang menerjemahkan daftar flat json apa saja objek ke csv.

Lewati file input.json sebagai argumen pertama pada baris perintah.

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())
Mike Repass
sumber
2
Komentar penting - kode ini menyimpulkan kolom / header dari bidang di baris pertama. Jika data json Anda memiliki kolom 'bergerigi', misalkan katakanlah row1 memiliki 5 kolom tetapi row2 memiliki 6 kolom, maka Anda perlu melakukan pass pertama pada data untuk mendapatkan set total semua kolom dan menggunakannya sebagai header.
Mike Repass
Dengan data yang saya miliki ini adalah bagian besar dari solusi yang saya butuhkan, karena JSON saya tidak bergerigi, itu bekerja dengan sangat baik dengan sedikit penyesuaian untuk output karena saya menjalankan ini dalam skrip yang ada.
MichaelF
1
Kode ini juga mengasumsikan bahwa nilai-nilai akan dikeluarkan dalam urutan yang sama dengan tombol pada baris tajuk. Meskipun itu mungkin berhasil karena keberuntungan, itu sama sekali tidak dijamin.
RyanHennig
Mendapatkan kesalahan penyandian. Adakah yang tahu bagaimana cara menambahkan encoding ke utf-8?
Elad Tabak
25

Kode ini harus bekerja untuk Anda, dengan asumsi bahwa data JSON Anda ada dalam file bernama 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)
Dan Loewenherz
sumber
1
Hmmm, tidak - csv_file.writerow(tidak ada f.writerowtentu saja, saya menganggap Anda membuat kesalahan ketik di sana!) Ingin urutan, bukan dict - dan dalam contoh Anda, setiap item adalah dict. Ini akan bekerja untuk kasus khusus LAIN, seperti yang saya identifikasi dalam jawaban saya - di mana file JSON memiliki array array; itu tidak berfungsi untuk array objek, yang merupakan kasus khusus yang tampaknya Anda coba selesaikan (yang membutuhkan csv.DictWriter- dan tentu saja Anda perlu mengekstrak nama bidang dan memutuskan pesanan untuk membuat instantiate itu ! -).
Alex Martelli
@DanLoewenherz Itu tidak berfungsi pada versi Python terbaru. TypeError: hanya dapat menyatukan daftar (bukan "dict_values") ke daftar
Apolo Radomer
18

Ini akan mudah digunakan csv.DictWriter(), implementasi terperinci bisa seperti ini:

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

Perhatikan bahwa ini mengasumsikan bahwa semua objek JSON Anda memiliki bidang yang sama.

Berikut ini referensi yang dapat membantu Anda.

ReturnHttp402
sumber
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Mathieu
3
@purplepsycho Saya menemukan jawaban ini dengan downvote, yang pantas hanya sebagai tautan. Pengguna baru, yang mungkin tidak menyadari bahwa tautan saja bukan jawaban yang baik, telah memperbaikinya. Saya terbalik; mungkin Anda juga bisa, untuk mendorong pengguna baru untuk terus berpartisipasi dalam komunitas kami?
Mawg mengatakan mengembalikan Monica
6

Saya mengalami masalah dengan solusi yang diusulkan Dan , tetapi ini berhasil bagi saya:

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

Di mana "test.json" berisi yang berikut:

[ 
{"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 } }
]
Amanda
sumber
Mendapat kesalahan saat mencoba program Anda pada data sampel C: \ curl> python json2csv.py Traceback (panggilan terakhir terakhir): File "json2csv.py", baris 11, di <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. values ​​()) TypeError: hanya dapat meringkas daftar (bukan "dict_values") untuk dicantumkan
Mian Asbat Ahmad
Mencoba lagi sekarang di Python 2.7.9 dan berfungsi dengan baik untuk saya.
Amanda
6

Gunakan json_normalizedari pandas:

  • Mengingat data yang diberikan, dalam file bernama test.json
  • encoding='utf-8' mungkin tidak perlu.
  • Kode berikut memanfaatkan pathlibperpustakaan
    • .open adalah metode pathlib
    • Bekerja dengan jalur non-Windows juga
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')

Output 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

Sumberdaya lain untuk objek JSON yang lebih berat:

Trenton McKinney
sumber
4

Seperti disebutkan dalam jawaban sebelumnya, kesulitan dalam mengubah json ke csv adalah karena file json dapat berisi kamus bersarang dan karenanya menjadi struktur data multidimensi ayat csv yang merupakan struktur data 2D. Namun, cara yang baik untuk mengubah struktur multidimensi menjadi csv adalah memiliki beberapa csv yang diikat bersama dengan kunci primer.

Dalam contoh Anda, keluaran csv pertama memiliki kolom "pk", "model", "bidang" sebagai kolom Anda. Nilai untuk "pk", dan "model" mudah didapat tetapi karena kolom "bidang" berisi kamus, itu haruslah csv sendiri dan karena "codename" tampaknya menjadi kunci utama, Anda dapat menggunakan input untuk "bidang" untuk menyelesaikan csv pertama. Csv kedua berisi kamus dari kolom "bidang" dengan nama kode sebagai kunci utama yang dapat digunakan untuk mengikat 2 csv bersama-sama.

Ini adalah solusi untuk file json Anda yang mengubah kamus bersarang menjadi 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")
dmathewwws
sumber
4

Saya tahu sudah lama sejak pertanyaan ini ditanyakan tetapi saya pikir saya dapat menambahkan jawaban orang lain dan membagikan posting blog yang menurut saya menjelaskan solusinya dengan cara yang sangat ringkas.

Inilah tautannya

Buka file untuk ditulis

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

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

Pastikan untuk menutup file untuk menyimpan konten

employ_data.close()
pengguna3768804
sumber
3

Ini bukan cara yang sangat cerdas untuk melakukannya, tetapi saya memiliki masalah yang sama dan ini berhasil bagi saya:

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()
Juan Luis Martinez
sumber
3

Jawaban Alec luar biasa, tetapi tidak berfungsi jika ada beberapa tingkat bersarang. Berikut ini adalah versi yang dimodifikasi yang mendukung banyak level penyarangan. Itu juga membuat nama header sedikit lebih bagus jika objek bersarang sudah menentukan kunci sendiri (misalnya Firebase Analytics / BigTable / BigQuery data):

"""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)
phreakhead
sumber
2

Ini bekerja relatif baik. Ini meratakan json untuk menulisnya ke file csv. Elemen bersarang dikelola :)

Itu untuk 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)

Nikmati.

Loïc
sumber
File .csv tidak dihasilkan, sebaliknya, teks csv adalah output ke konsol. Juga, json.loadstidak berfungsi, saya membuatnya bekerja dengan json.load, yang dengan baik menghasilkan objek daftar. Ketiga, elemen bersarang hilang.
ZygD
2

Cara sederhana saya untuk menyelesaikan ini:

Buat file Python baru seperti: json_to_csv.py

Tambahkan kode ini:

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

Setelah menambahkan kode ini, simpan file dan jalankan di terminal:

python json_to_csv.py input.txt output.csv

Saya harap ini membantu Anda.

SAMPAI JUMPA!

Gabriel Pires
sumber
1
Sampel ini bekerja seperti pesona! terima kasih sudah berbagi saya dapat mengonversi file json saya ke CSV menggunakan skrip python ini
Mostafa
2

Anehnya, saya menemukan bahwa tidak ada jawaban yang diposting di sini sejauh ini dengan benar menangani semua skenario yang mungkin (misalnya, dicts bersarang, daftar bersarang, Nilai tidak ada, dll).

Solusi ini harus bekerja di semua skenario:

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
Max Berman
sumber
2

Coba ini

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())
Hasee Amarathunga
sumber
2

Kode ini berfungsi untuk semua file json yang diberikan

# -*- 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()
Ram Prajapati
sumber
1

Jawaban Alec McGail yang dimodifikasi untuk mendukung JSON dengan daftar di dalamnya

    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

Terima kasih!

Sawan Vaidya
sumber
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)
Dnyaneshwar Shendurwadkar
sumber
1

Jika kita perhatikan contoh di bawah ini untuk mengonversi file berformat json menjadi file berformat csv.

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

Kode di bawah ini akan mengonversi file json (data3.json) menjadi file 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')])

Kode yang disebutkan di atas telah dieksekusi di pycharm yang diinstal secara lokal dan telah berhasil mengkonversi file json ke file csv. Semoga bantuan ini dapat mengonversi file.

SABYASACHI SAHA
sumber
0

Karena data tampak dalam format kamus, maka Anda harus benar-benar menggunakan csv.DictWriter () untuk benar-benar menampilkan baris dengan informasi header yang sesuai. Ini seharusnya memungkinkan konversi ditangani agak lebih mudah. Parameter fieldnames kemudian akan mengatur pesanan dengan benar sementara output dari baris pertama sebagai header akan memungkinkannya untuk dibaca dan diproses kemudian oleh csv.DictReader ().

Misalnya, Mike Repass digunakan

output = csv.writer(sys.stdout)

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

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

Namun, ubah saja pengaturan awal menjadi output = csv.DictWriter (pengaturan file, fieldnames = data [0] .keys ())

Perhatikan bahwa karena urutan elemen dalam kamus tidak ditentukan, Anda mungkin harus membuat entri fieldnames secara eksplisit. Setelah Anda melakukan itu, penulis akan bekerja. Penulisan kemudian bekerja seperti yang ditunjukkan pada awalnya.

sabbahillel
sumber
0

Sayangnya saya tidak memiliki reputasi untuk memberikan kontribusi kecil untuk jawaban @Alec McGail yang luar biasa. Saya menggunakan Python3 dan saya harus mengubah peta menjadi daftar setelah komentar @Alexis R.

Tambahan lagi saya telah menemukan penulis csv menambahkan CR ekstra ke file (saya memiliki baris kosong untuk setiap baris dengan data di dalam file csv). Solusinya sangat mudah mengikuti jawaban @Jason R. Coombs untuk utas ini: CSV dengan Python menambahkan carriage return tambahan

Anda hanya perlu menambahkan parameter lineterminator = '\ n' ke csv.writer. Boleh jadi:csv_w = csv.writer( out_file, lineterminator='\n' )

derwyddon
sumber
0

Anda dapat menggunakan kode ini untuk mengonversi file json ke file csv Setelah membaca file tersebut, saya mengonversi objek ke bingkai data panda dan kemudian menyimpannya ke file 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)
Terminator17
sumber
ini tidak memperhitungkan sub-bidang (seperti "bidang" pada contoh) - sub-objek berada dalam satu kolom alih-alih isinya dipisahkan ke dalam masing-masing kolom juga.
Cribber
0

Saya mungkin terlambat ke pesta, tapi saya pikir, saya sudah berurusan dengan masalah yang sama. Saya punya file json yang terlihat seperti ini

Struktur File JSON

Saya hanya ingin mengekstrak beberapa kunci / nilai dari file json ini. Jadi, saya menulis kode berikut untuk mengekstrak yang sama.

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

Saya harap ini akan membantu. Untuk detail tentang cara kerja kode ini, Anda dapat memeriksa di sini

Udit Hari Vashisht
sumber
0

Ini adalah modifikasi dari jawaban @ MikeRepass. Versi ini menulis CSV ke file, dan berfungsi untuk Python 2 dan 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())
cowlinator
sumber