Wie kann ich JSON in CSV konvertieren?

183

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:
    csv_file.writerow(item)

f.close()

Es hat jedoch nicht funktioniert. Ich benutze Django und der Fehler, den ich erhalten habe, ist:

file' object has no attribute 'writerow'

Ich habe dann 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:
    f.writerow(item)  # ← changed

f.close()

Ich bekomme dann den Fehler:

sequence expected

Beispiel-JSON-Datei:

[{
        "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
        }
    }
]
kleiner Fisch
quelle
1
Für csv_file.writerow (item) muss das Element eine einfache Liste von Zeichenfolgen oder Zahlen sein. Versuchen Sie, jedes JSON-Objekt in eine flache Liste zu konvertieren, z. B. {"pk": 22, "model": "auth.permission"} wird zu [22, auth.permission].
Suppressingfire
Ein einfacher Ansatz hierfür ist die Verwendung jq, wie hier beschrieben: stackoverflow.com/questions/32960857/…
Micah Elliott
Alternative von Drittanbietern : json-csv.com (für einmalige Konvertierungen) oder json-csv.com/api zur Automatisierung mit Python. Dies ist eine einfache Lösung für komplexere JSON-Strukturen.
Stack Man

Antworten:

127

Erstens verfügt Ihr JSON über verschachtelte Objekte, sodass es normalerweise nicht direkt in CSV konvertiert werden kann. Sie müssen das in etwa so ä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 folgende Ausgabe:

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
SIE
quelle
2
Das ist Arbeit, aber tut mir leid, bevor ich etwas bekommen kann, das nicht hart ist. Ich finde es besser. Ich kann f.writerow (a) verwenden und das a ist eine Variable, die ich vorher deklariere. Danke vorher
little_fish
Bei mir funktioniert das fast perfekt. In der exportierten CSV sind einige Felder von [u'und umgeben ']. Was ist die Problemumgehung (ohne Nachbearbeitung)? wenn es eine gibt ... :)
Dror
3
Unten habe ich einen Weg gezeigt, es allgemeiner zu machen, ohne es hart codieren zu müssen
Alec McGail
4
Hey, ich habe es versucht, aber ich bekomme eine TypeError: a bytes-like object is required, not 'str'beif.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Aditya Hariharan
8
für Python3 ändern Sie die Zeile mit dem Öffnen der CSV-Datei inf = csv.writer(open("test.csv", "w", newline=''))
PiotrK
116

Mit der pandas Bibliothek ist dies so einfach wie mit zwei Befehlen!

pandas.read_json()

So konvertieren Sie eine JSON-Zeichenfolge in ein Pandas-Objekt (entweder eine Serie oder einen Datenrahmen). Dann wurde angenommen, dass die Ergebnisse wie folgt gespeichert wurden df:

df.to_csv()

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

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

vmg
quelle
1
Dies ist eine fantastische Antwort (+1) - so einfach und .to_csv()sehr leistungsfähig (z. B. kostenlose Spaltenfilterung). Ich muss Pandas lernen.
WoJ
3
Wie bereits erwähnt, funktioniert diese Antwort für die Daten in dieser Frage nicht. orient='records'muss gesetzt werden, aber jede Zeile von fieldswird immer noch eine sein dict, was nicht das ist, was das OP angefordert hat.
Trenton McKinney
88

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 auf Ihrem 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 Eingabearray von JSON-Objekten:

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

und Finden der relevanten Spaltennamen:

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

Es ist nicht schwer, dies über 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!

Alec McGail
quelle
Mit Python 3.6 musste ich eine Liste des abgeflachten JSON erstellen, damit die letzte Schleife funktioniert: "input = list (map (lambda x: flattenjson (x," __ "), input))". Ich verstehe nicht, warum das iterable nicht genug ist. Ich musste auch die Codierung beim Öffnen der Ausgabedatei angeben, da meine Daten UTF8 verwenden. Es hat definitiv geholfen, danke !!
Alexis R
Das ist großartig, danke Alec! Ich habe es so geändert, dass es mit mehreren Verschachtelungsebenen funktioniert
phreakhead
35

JSON kann eine Vielzahl von Datenstrukturen darstellen - ein JS- "Objekt" ähnelt in etwa einem Python-Diktat (mit Zeichenfolgenschlüsseln), ein JS- "Array" ähnelt in etwa einer Python-Liste, und Sie können sie so lange verschachteln, wie das endgültige " Blatt "Elemente sind Zahlen oder Zeichenfolgen.

CSV kann im Wesentlichen nur eine 2D-Tabelle darstellen - optional mit einer ersten Zeile von "Überschriften", dh "Spaltennamen", wodurch die Tabelle als Liste von Diktaten interpretiert werden kann, anstatt als normale Interpretation eine Liste von Listen (wieder können "Blatt" -Elemente Zahlen oder Zeichenfolgen sein).

Im allgemeinen Fall können Sie eine beliebige JSON-Struktur nicht in eine CSV übersetzen. In einigen besonderen Fällen können Sie (Array von Arrays ohne weitere Verschachtelung; Arrays von Objekten, die alle genau die gleichen Schlüssel haben). Welcher Sonderfall trifft gegebenenfalls auf Ihr Problem zu? Die Details der Lösung hängen davon ab, welchen Sonderfall Sie haben. Angesichts der erstaunlichen Tatsache, dass Sie nicht einmal erwähnen, welche zutreffend ist, habe ich den Verdacht, dass Sie die Einschränkung nicht berücksichtigt haben, und es gibt auch keinen brauchbaren Fall, und Ihr Problem ist unmöglich zu lösen. Aber bitte klären!

Alex Martelli
quelle
31

Eine generische Lösung, die jede JSON-Liste flacher Objekte in CSV übersetzt.

Übergeben Sie die Datei input.json 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())
Mike Repass
quelle
2
Ein wichtiger Kommentar - dieser Code leitet die Spalten / Überschriften aus den Feldern in der ersten Zeile ab. Wenn Ihre JSON-Daten "gezackte" Spalten haben, dh Zeile 1 hat 5 Spalten, aber Zeile 2 hat 6 Spalten, müssen Sie einen ersten Durchlauf über die Daten durchführen, um den Gesamtsatz aller Spalten abzurufen und diese als Überschriften zu verwenden.
Mike Repass
Mit den Daten, die ich hatte, war dies ein großer Teil der Lösung, die ich brauchte, da mein JSON nicht gezackt war, funktionierte es wunderbar mit einigen geringfügigen Anpassungen für die Ausgabe, da ich dies in einem vorhandenen Skript ausführte.
MichaelF
1
In diesem Code wird auch davon ausgegangen, dass die Werte in derselben Reihenfolge wie die Schlüssel in der Kopfzeile ausgegeben werden. Das mag zwar durch Glück funktioniert haben, ist aber keineswegs garantiert.
RyanHennig
Codierungsfehler erhalten. Irgendeine Idee, wie man utf-8 Codierung hinzufügt?
Elad Tabak
25

Dieser Code sollte für Sie funktionieren, vorausgesetzt, Ihre JSON-Daten befinden sich in einer Datei mit dem Namen 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
quelle
1
Hmmm, nein - csv_file.writerow(es gibt f.writerownatürlich keine , ich nehme an, Sie haben dort einen Tippfehler gemacht!) Möchte eine Sequenz, kein Diktat - und in Ihrem Beispiel ist jedes Element ein Diktat. Dies würde für den ANDEREN Sonderfall funktionieren, wie ich in meiner Antwort festgestellt habe - wo die JSON-Datei ein Array von Arrays enthält; Es funktioniert nicht für ein Array von Objekten. Dies ist der Sonderfall, den Sie anscheinend zu lösen versuchen (für diesen ist ein erforderlich csv.DictWriter- und natürlich müssen Sie die Feldnamen extrahieren und eine Reihenfolge festlegen, um sie zu instanziieren ! -).
Alex Martelli
@DanLoewenherz Das funktioniert bei aktuellen Python-Versionen nicht. TypeError: kann nur Liste (nicht "dict_values") mit Liste verketten
Apolo Radomer
18

Es wird einfach zu bedienen sein csv.DictWriter(), die detaillierte Implementierung kann folgendermaßen 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 voraussetzt, dass alle Ihre JSON-Objekte dieselben Felder haben.

Hier ist die Referenz, die Ihnen helfen kann.

ReturnHttp402
quelle
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Aus dem Rückblick
Mathieu
3
@purplepsycho Ich fand diese Antwort mit einer Abwertung, die nur als Link verdient war. Der neue Benutzer, der möglicherweise nicht wusste, dass nur ein Link keine gute Antwort ist, hat dies korrigiert. Ich stimmte zu; Vielleicht könnten Sie auch den neuen Benutzer ermutigen, weiterhin an unserer Community teilzunehmen?
Mawg sagt, Monica am
6

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

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

Wobei "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 } }
]
Amanda
quelle
Beim Testen Ihres Programms mit Ihren Beispieldaten ist ein Fehler aufgetreten. C: \ curl> python json2csv.py Traceback (letzter Aufruf zuletzt): Datei "json2csv.py", Zeile 11, in <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. values ​​()) TypeError: kann nur die Liste (nicht "dict_values") mit der Liste
verknüpfen
Ich habe es gerade in Python 2.7.9 noch einmal versucht und es funktioniert gut für mich.
Amanda
6

Verwendung json_normalizevon pandas:

  • Angesichts der bereitgestellten Daten in einer Datei mit dem Namen test.json
  • encoding='utf-8' ist möglicherweise nicht erforderlich.
  • Der folgende Code nutzt die pathlibBibliothek
    • .open ist eine Methode von pathlib
    • Funktioniert auch mit Nicht-Windows-Pfaden
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-Ausgabe:

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

Andere Ressourcen für stärker verschachtelte JSON-Objekte:

Trenton McKinney
quelle
4

Wie in den vorherigen Antworten erwähnt, besteht die Schwierigkeit beim Konvertieren von json in csv darin, dass eine json-Datei verschachtelte Wörterbücher enthalten kann und daher eine mehrdimensionale Datenstruktur gegenüber einer csv ist, bei der es sich um eine 2D-Datenstruktur handelt. Eine gute Möglichkeit, eine mehrdimensionale Struktur in eine CSV umzuwandeln, besteht darin, mehrere CSVs zu haben, die mit Primärschlüsseln verknüpft sind.

In Ihrem Beispiel enthält die erste CSV-Ausgabe die Spalten "pk", "model" und "fields" als Spalten. Die Werte für "pk" und "model" sind leicht zu ermitteln. Da die Spalte "fields" jedoch ein Wörterbuch enthält, sollte es sich um eine eigene CSV handeln. Da "Codename" als Primärschlüssel angezeigt wird, können Sie diese als Eingabe verwenden für "Felder", um die erste CSV zu vervollständigen. Die zweite CSV enthält das Wörterbuch aus der Spalte "Felder" mit dem Codenamen 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")
dmathewwws
quelle
4

Ich weiß, dass diese Frage schon lange nicht mehr gestellt wurde, aber ich dachte, ich könnte die Antwort aller anderen ergänzen und einen Blog-Beitrag teilen, der meiner Meinung nach die Lösung auf sehr präzise Weise 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()
user3768804
quelle
3

Es ist keine sehr kluge Methode, aber ich hatte das gleiche Problem und das hat bei mir 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()
Juan Luis Martinez
quelle
3

Alecs Antwort ist großartig, aber es funktioniert nicht, wenn es mehrere Verschachtelungsebenen gibt. Hier ist eine modifizierte Version, die mehrere Verschachtelungsebenen unterstützt. Außerdem werden die Headernamen etwas schöner, 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 __name__ == '__main__':
  main(sys.argv)
Phreakhead
quelle
2

Das funktioniert relativ gut. Es flacht den JSON ab, um ihn in eine CSV-Datei zu schreiben. Verschachtelte Elemente werden verwaltet :)

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.

Loïc
quelle
CSV-Datei wurde nicht generiert, stattdessen wurde CSV-Text an die Konsole ausgegeben. Funktionierte auch json.loadsnicht, ich habe es zum Laufen gebracht json.load, was ein Listenobjekt ergibt. Drittens gingen verschachtelte Elemente verloren.
ZygD
2

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

Speichern Sie nach dem Hinzufügen dieses Codes 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!

Gabriel Pires
quelle
1
Dieses Beispiel wirkt wie ein Zauber! danke fürs teilen ich konnte meine json datei mit diesem python script in CSV konvertieren
Mostafa
2

Überraschenderweise stellte ich fest, dass keine der hier veröffentlichten Antworten alle möglichen Szenarien korrekt behandelt (z. B. verschachtelte Dikte, verschachtelte Listen, Keine Werte usw.).

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

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

Dieser Code funktioniert für jede gegebene 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()
Ram Prajapati
quelle
1

Die Antwort von Alec McGail wurde geändert, 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!

Sawan Vaidya
quelle
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
quelle
1

Wenn wir das folgende Beispiel für die Konvertierung der Datei im JSON-Format in eine CSV-formatierte Datei betrachten.

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

Der folgende Code konvertiert die JSON-Datei (data3.json) in eine CSV-Datei (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')])

Der oben genannte Code wurde im lokal installierten Pycharm ausgeführt und hat die JSON-Datei erfolgreich in die CSV-Datei konvertiert. Hoffe diese Hilfe beim Konvertieren der Dateien.

SABYASACHI SAHA
quelle
0

Da die Daten in einem Wörterbuchformat zu sein scheinen, sollten Sie tatsächlich csv.DictWriter () verwenden, um die Zeilen mit den entsprechenden Kopfzeileninformationen tatsächlich auszugeben. Dies sollte eine etwas einfachere Konvertierung ermöglichen. Der Parameter fieldnames würde dann die Reihenfolge ordnungsgemäß einrichten, während die Ausgabe der ersten Zeile als Überschriften es ermöglichen würde, sie später von csv.DictReader () zu lesen und zu verarbeiten.

Zum Beispiel verwendet Mike Repass

output = csv.writer(sys.stdout)

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

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

Ändern Sie jedoch einfach die Ersteinrichtung in output = csv.DictWriter (Dateigruppe, Feldnamen = Daten [0] .keys ()).

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

Sabbahillel
quelle
0

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

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

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

derwyddon
quelle
0

Mit diesem Code können Sie eine JSON-Datei in eine CSV-Datei konvertieren. Nach dem Lesen der Datei konvertiere ich das Objekt in einen Pandas-Datenrahmen 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)
Terminator17
quelle
Dies berücksichtigt keine Unterfelder (wie z. B. "Felder" im Beispiel) - das Unterobjekt befindet sich in einer Spalte, anstatt dass sein Inhalt ebenfalls in einzelne Spalten unterteilt ist.
Cribber
0

Ich komme vielleicht zu spät zur Party, aber ich denke, ich habe mich mit dem ähnlichen Problem befasst. Ich hatte eine JSON-Datei, die so aussah

JSON-Dateistruktur

Ich wollte nur einige Schlüssel / Werte aus dieser JSON-Datei extrahieren. Also habe ich den folgenden Code geschrieben, um dasselbe zu extrahieren.

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

Ich hoffe das wird helfen. Einzelheiten zur Funktionsweise dieses Codes finden Sie hier

Udit Hari Vashisht
quelle
0

Dies ist eine Modifikation der Antwort von @ MikeRepass. Diese Version schreibt die CSV in eine Datei und funktioniert sowohl für Python 2 als auch für 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
quelle