it-swarm.com.de

Wie kann ich JSON in CSV konvertieren?

Ich habe eine JSON-Datei, die ich in eine CSV-Datei konvertieren möchte. Wie kann ich das mit Python machen?

Ich habe es versucht:

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)

f.close()

Es hat jedoch nicht funktioniert. Ich benutze Django und der Fehler ist:

file' object has no attribute 'writerow'

Also habe ich folgendes versucht:

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

Ich bekomme dann den Fehler:

sequence expected

Json-Beispieldatei:

[
  {
    "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
    }
  }
]
131
little_fish

Ich bin nicht sicher, ob diese Frage bereits gelöst ist oder nicht, aber lassen Sie mich das, was ich getan habe, als Referenz einfügen.

Erstens hat Ihr JSON verschachtelte Objekte, daher kann es normalerweise nicht direkt in CSV ..__ konvertiert werden. Sie müssen dies in etwa wie folgt ändern:

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

Hier ist mein Code, um daraus CSV zu generieren:

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

Sie erhalten die Ausgabe als:

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
100
YOU

Ich gehe davon aus, dass Ihre JSON-Datei in eine Liste von Wörterbüchern dekodiert wird. Zuerst benötigen wir eine Funktion, die die JSON-Objekte reduziert: 

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

Das Ergebnis der Ausführung dieses Snippets für Ihr JSON-Objekt:

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

ist

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

Nach dem Anwenden dieser Funktion auf jedes Diktat im Eingabefeld von JSON-Objekten:

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

und finden Sie die relevanten Spaltennamen:

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

es ist nicht schwer, dies durch das csv-modul auszuführen:

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

Ich hoffe das hilft!

76
Alec McGail

Mit der pandasBibliothek , ist dies genauso einfach wie die Verwendung von zwei Befehlen!

pandas.read_json()

So konvertieren Sie einen JSON-String in ein Pandas-Objekt (entweder eine Serie oder ein Datenframe). Dann werden die Ergebnisse als df gespeichert:

df.to_csv()

Die kann entweder einen String zurückgeben oder direkt in eine CSV-Datei schreiben.

Aufgrund der Ausführlichkeit der vorherigen Antworten sollten wir uns alle bei Pandas für die Abkürzung bedanken.

57
vmg

JSON kann eine Vielzahl von Datenstrukturen darstellen - ein JS- "Objekt" ähnelt in etwa einem Python-Diktat (mit Zeichenfolgeschlüsseln), ein JS-"Array" in etwa einer Python-Liste. leaf "Elemente sind Zahlen oder Strings.

CSV kann im Wesentlichen nur eine 2-D-Tabelle darstellen - optional mit einer ersten Zeile von "Headern", dh "Spaltennamen", die die Tabelle als Liste von Diagrammen interpretierbar machen können, anstelle der normalen Interpretation eine Liste von Listen (wiederum können "Blätter" -Elemente Zahlen oder Strings sein).

Daher können Sie im Allgemeinen keine beliebige JSON-Struktur in eine CSV-Datei übersetzen. In einigen speziellen Fällen können Sie (Arrays von Arrays ohne weitere Verschachtelung; Arrays von Objekten, die alle exakt dieselben Schlüssel haben). Welcher Sonderfall trifft auf Ihr Problem zu? Die Details der Lösung hängen davon ab, welchen speziellen Fall Sie haben. In Anbetracht der erstaunlichen Tatsache, dass Sie nicht einmal erwähnen, welche zutreffend ist, vermute ich, dass Sie die Einschränkung möglicherweise nicht in Betracht gezogen haben, und es gibt auch keinen anwendbaren Fall, und Ihr Problem ist unmöglich zu lösen. Aber bitte klären Sie!

34
Alex Martelli

Eine generische Lösung, die jede Json-Liste von flat objects in csv übersetzt.

Übergeben Sie die input.json-Datei als erstes Argument in der Befehlszeile.

import csv, json, sys

input = open(sys.argv[1])
data = json.load(input)
input.close()

output = csv.writer(sys.stdout)

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

for row in data:
    output.writerow(row.values())
25
Mike Repass

Dieser Code sollte für Sie funktionieren, vorausgesetzt, Ihre JSON-Daten befinden sich in einer Datei namens data.json.

import json
import csv

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

with open("data.csv", "w") as file:
    csv_file = csv.writer(file)
    for item in data:
        csv_file.writerow([item['pk'], item['model']] + item['fields'].values())
21
Dan Loewenherz

Es wird einfach sein, csv.DictWriter() zu verwenden, die detaillierte Implementierung kann wie folgt aussehen:

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

Beachten Sie, dass dies davon ausgeht, dass alle JSON-Objekte die gleichen Felder haben. 

Hier ist das reference , das Ihnen helfen kann.

15
ReturnHttp402

Ich hatte Probleme mit Dans Lösungsvorschlag , aber das hat für mich funktioniert:

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

Wo "test.json" Folgendes enthielt:

[ 
{"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 } }
]
6
Amanda

Wie in den vorangegangenen Antworten erwähnt, besteht die Schwierigkeit bei der Konvertierung von Json in CSV darin, dass eine Json-Datei verschachtelte Wörterbücher enthalten kann und daher eine multidimensionale Datenstruktur gegenüber einer CSV-Datei sein kann, bei der es sich um eine 2D-Datenstruktur handelt. Eine mehrdimensionale Struktur kann jedoch zu einer CSV werden, wenn mehrere CSVs vorhanden sind, die mit Primärschlüsseln verknüpft sind.

In Ihrem Beispiel hat die erste CSV-Ausgabe die Spalten "pk", "model", "fields" als Spalten. Werte für "pk" und "model" sind leicht zu erhalten. Da jedoch die Spalte "Felder" ein Wörterbuch enthält, sollte es eine eigene CSV-Datei sein. Da "Codename" als Primärschlüssel erscheint, können Sie die Eingabe als Eingabe verwenden für "Felder", um die erste CSV abzuschließen. Das zweite CSV enthält das Wörterbuch aus der Spalte "Felder" mit Codename als Primärschlüssel, mit dem die beiden CSVs miteinander verbunden werden können.

Hier ist eine Lösung für Ihre Json-Datei, die verschachtelte Wörterbücher in 2 CSVs konvertiert.

import csv
import json

def readAndWrite(inputFileName, primaryKey=""):
    input = open(inputFileName+".json")
    data = json.load(input)
    input.close()

    header = set()

    if primaryKey != "":
        outputFileName = inputFileName+"-"+primaryKey
        if inputFileName == "data":
            for i in data:
                for j in i["fields"].keys():
                    if j not in header:
                        header.add(j)
    else:
        outputFileName = inputFileName
        for i in data:
            for j in i.keys():
                if j not in header:
                    header.add(j)

    with open(outputFileName+".csv", 'wb') as output_file:
        fieldnames = list(header)
        writer = csv.DictWriter(output_file, fieldnames, delimiter=',', quotechar='"')
        writer.writeheader()
        for x in data:
            row_value = {}
            if primaryKey == "":
                for y in x.keys():
                    yValue = x.get(y)
                    if type(yValue) == int or type(yValue) == bool or type(yValue) == float or type(yValue) == list:
                        row_value[y] = str(yValue).encode('utf8')
                    Elif type(yValue) != dict:
                        row_value[y] = yValue.encode('utf8')
                    else:
                        if inputFileName == "data":
                            row_value[y] = yValue["codename"].encode('utf8')
                            readAndWrite(inputFileName, primaryKey="codename")
                writer.writerow(row_value)
            Elif primaryKey == "codename":
                for y in x["fields"].keys():
                    yValue = x["fields"].get(y)
                    if type(yValue) == int or type(yValue) == bool or type(yValue) == float or type(yValue) == list:
                        row_value[y] = str(yValue).encode('utf8')
                    Elif type(yValue) != dict:
                        row_value[y] = yValue.encode('utf8')
                writer.writerow(row_value)

readAndWrite("data")
4
dmathewwws

Ich weiß, es ist lange her, seit diese Frage gestellt wurde, aber ich dachte, ich könnte die Antwort aller anderen hinzufügen und einen Blogbeitrag veröffentlichen, von dem ich denke, dass er die Lösung auf eine sehr kurze Art erklärt.

Hier ist der Link

Öffnen Sie eine Datei zum Schreiben

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

Erstellen Sie das CSV-Writer-Objekt

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

Stellen Sie sicher, dass Sie die Datei schließen, um den Inhalt zu speichern

employ_data.close()
4
user3768804

Mein einfacher Weg, dies zu lösen:

Erstellen Sie eine neue Python-Datei wie: json_to_csv.py

Fügen Sie diesen Code hinzu: 

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

Nachdem Sie diesen Code hinzugefügt haben, speichern Sie die Datei und führen Sie sie am Terminal aus:

python json_to_csv.py input.txt output.csv

Ich hoffe das hilft dir.

TSCHÜSS!

2
Gabriel Pires

Das funktioniert relativ gut ... __ Es flacher den Json, um ihn in eine CSV-Datei zu schreiben.

Das ist für 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)

genießen.

2
Loïc
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)

Dieser Code funktioniert für jede beliebige JSON-Datei

# -*- 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
Ram Prajapati

Alecs Antwort ist großartig, aber es funktioniert nicht, wenn es mehrere Verschachtelungsebenen gibt. Hier ist eine modifizierte Version, die mehrere Verschachtelungsebenen unterstützt. Dadurch werden die Headernamen auch ein bisschen netter, wenn das verschachtelte Objekt bereits einen eigenen Schlüssel angibt (z. B. Firebase Analytics/BigTable/BigQuery-Daten):

"""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 __== '__main__':
  main(sys.argv)
1
phreakhead

Versuche dies

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

Es ist keine sehr kluge Methode, aber ich hatte das gleiche Problem und das hat für mich funktioniert:

import csv

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

new_data = []

for i in data:
   flat = {}
   names = i.keys()
   for n in names:
      try:
         if len(i[n].keys()) > 0:
            for ii in i[n].keys():
               flat[n+"_"+ii] = i[n][ii]
      except:
         flat[n] = i[n]
   new_data.append(flat)  

f = open(filename, "r")
writer = csv.DictWriter(f, new_data[0].keys())
writer.writeheader()
for row in new_data:
   writer.writerow(row)
f.close()
1

Alec McGails Antwort wurde modifiziert, um JSON mit Listen zu unterstützen

    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

Vielen Dank!

1
Sawan Vaidya

Sie können diesen Code verwenden, um eine Json-Datei in eine CSV-Datei zu konvertieren. Nach dem Lesen der Datei konvertiere ich das Objekt in Pandas-Dataframe und speichere es dann in einer CSV-Datei

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)
0
Terminator17

Überraschenderweise fand ich heraus, dass keine der bisher veröffentlichten Antworten alle möglichen Szenarien (z. B. verschachtelte Diktate, verschachtelte Listen, keine Werte usw.) richtig behandelt.

Diese Lösung sollte in allen Szenarien funktionieren:

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
0
Max Berman

Da die Daten scheinbar in einem Wörterbuchformat vorliegen, sollten Sie csv.DictWriter () tatsächlich verwenden, um die Zeilen mit den entsprechenden Headerinformationen tatsächlich auszugeben. Dadurch sollte die Konvertierung etwas einfacher gehandhabt werden. Der fieldnames -Parameter würde dann die Reihenfolge richtig festlegen, während die Ausgabe der ersten Zeile als Kopfzeile ermöglichen würde, dass sie später von csv.DictReader () gelesen und verarbeitet werden kann.

Zum Beispiel wurde Mike Repass verwendet

output = csv.writer(sys.stdout)

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

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

Ändern Sie jedoch einfach das anfängliche Setup in output = csv.DictWriter (Dateisatz, Feldnamen = data [0] .keys ())

Da die Reihenfolge der Elemente in einem Wörterbuch nicht definiert ist, müssen Sie möglicherweise Feldnameneinträge explizit erstellen. Sobald Sie das getan haben, wird der Writerow funktionieren. Die Schreibvorgänge funktionieren dann wie ursprünglich gezeigt.

0
sabbahillel

Leider habe ich nicht den Ruf, einen kleinen Beitrag zu der erstaunlichen Antwort von @Alec McGail zu leisten. Ich benutzte Python3 und musste die Karte nach dem @Alexis R-Kommentar in eine Liste konvertieren. 

Zusätzlich habe ich festgestellt, dass der CSV-Writer der Datei eine zusätzliche CR hinzufügte (ich habe eine leere Zeile für jede Zeile mit Daten in der CSV-Datei). Die Lösung war nach der Antwort von @Jason R. Coombs auf diesen Thread sehr einfach: CSV in Python fügte einen zusätzlichen Wagenrücklauf hinzu

Sie müssen einfach den Parameter lineterminator = '\ n' zum csv.writer hinzufügen. Es wird sein: csv_w = csv.writer( out_file, lineterminator='\n' )

0
derwyddon