Come posso convertire JSON in CSV?


184

Ho un file JSON che voglio convertire in un file CSV. Come posso farlo con Python?

Provai:

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

Tuttavia, non ha funzionato. Sto usando Django e l'errore che ho ricevuto è:

file' object has no attribute 'writerow'

Ho quindi provato quanto segue:

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

Ottengo quindi l'errore:

sequence expected

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

1
csv_file.writerow (item) richiede che l'elemento sia un semplice elenco di stringhe o numeri. Prova a convertire ogni oggetto json in un elenco semplice, come {"pk": 22, "model": "auth.permission"} diventerebbe [22, auth.permission].
Sopprimere il

1
Un approccio semplice a questo sta usando jq, come descritto qui: stackoverflow.com/questions/32960857/…
Micah Elliott,

Alternativa di terze parti: json-csv.com (per conversioni una tantum) o json-csv.com/api per automatizzare con Python. Questa è una soluzione semplice per strutture JSON più complesse.
Stack Man,

Risposte:


129

Innanzitutto, il JSON ha oggetti nidificati, quindi normalmente non può essere convertito direttamente in CSV. Devi cambiarlo in qualcosa del genere:

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

Ecco il mio codice per generare CSV da quello:

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

Otterrai un output come:

pk,model,codename,name,content_type
22,auth.permission,add_logentry,Can add log entry,8
23,auth.permission,change_logentry,Can change log entry,8
24,auth.permission,delete_logentry,Can delete log entry,8

2
questo è un lavoro, ma scusami prima, posso ottenere qualcosa che non è un codice difficile, cosa è meglio, posso usare f.writerow (a) e la a è una variabel che dichiaro prima grazie
little_fish

Per me questo funziona quasi perfettamente. Nel CSV esportato, alcuni dei campi sono circondati da [u'e ']. Qual è la soluzione alternativa (non post-elaborazione)? se ce n'è uno ... :)
Dror

3
Di seguito ho mostrato un modo per farlo più in generale, senza doverlo codificare
Alec McGail,

4
hey, ho provato questo, ma io sto diventando un TypeError: a bytes-like object is required, not 'str'af.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Aditya Hariharan

8
per python3 cambia riga con l'apertura del file CSV inf = csv.writer(open("test.csv", "w", newline=''))
PiotrK

119

Con la pandas libreria , questo è facile come usare due comandi!

pandas.read_json()

Per convertire una stringa JSON in un oggetto Panda (una serie o un frame di dati). Quindi, supponendo che i risultati siano stati memorizzati come df:

df.to_csv()

Che può restituire una stringa o scrivere direttamente in un file CSV.

Sulla base della verbosità delle risposte precedenti, dovremmo tutti ringraziare i panda per la scorciatoia.


1
Questa è una risposta fantastica (+1) - così semplice ed .to_csv()è davvero potente (filtraggio gratuito delle colonne, per esempio). Devo imparare i panda.
WoJ

3
Come sottolineato, questa risposta non funziona per i dati in questa domanda. orient='records'deve essere impostato, ma ogni riga fieldssarà comunque a dict, che non è ciò che l'OP ha richiesto.
Trenton McKinney,

90

Suppongo che il tuo file JSON verrà decodificato in un elenco di dizionari. Per prima cosa abbiamo bisogno di una funzione che appiattisca gli oggetti 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

Il risultato dell'esecuzione di questo frammento sul tuo oggetto JSON:

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

è

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

Dopo aver applicato questa funzione a ciascun dict nell'array di input degli oggetti JSON:

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

e trovare i nomi delle colonne pertinenti:

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

non è difficile eseguirlo attraverso il modulo 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 ) )

Spero che aiuti!


Usando Python 3.6, ho dovuto fare un elenco del JSON appiattito per far funzionare l'ultimo loop: "input = list (map (lambda x: flattenjson (x," __ "), input))". Non capisco perché l'iterabile non sia abbastanza però. Ho anche dovuto specificare la codifica all'apertura del file di output poiché i miei dati utilizzano UTF8. Ha sicuramente aiutato, grazie !!
Alexis R,

È fantastico, grazie Alec! Ho modificato per lavorare con più livelli di nidificazione: stackoverflow.com/a/57228641/473201
phreakhead

35

JSON può rappresentare un'ampia varietà di strutture di dati: un "oggetto" JS è approssimativamente come un dict Python (con chiavi stringa), un "array" JS approssimativamente come un elenco Python, e puoi annidarli fino alla fine " foglia "elementi sono numeri o stringhe.

CSV può essenzialmente rappresentare solo una tabella 2-D - opzionalmente con una prima riga di "intestazioni", cioè "nomi di colonna", che può rendere la tabella interpretabile come un elenco di dicts, invece della normale interpretazione, un elenco di liste (di nuovo, gli elementi "foglia" possono essere numeri o stringhe).

Quindi, nel caso generale, non è possibile tradurre una struttura JSON arbitraria in un CSV. In alcuni casi speciali è possibile (array di array senza ulteriori annidamenti; array di oggetti che hanno tutti esattamente le stesse chiavi). Quale caso speciale si applica al tuo problema? I dettagli della soluzione dipendono dal caso speciale che hai. Dato il fatto sorprendente che non hai nemmeno menzionato quale si applica, sospetto che potresti non aver considerato il vincolo, in realtà non si applica nemmeno il caso utilizzabile e il tuo problema è impossibile da risolvere. Ma per favore chiarisci!


31

Una soluzione generica che traduce qualsiasi elenco json di oggetti piatti in CSV.

Passa il file input.json come primo argomento sulla riga di comando.

import csv, json, sys

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

output = csv.writer(sys.stdout)

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

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

2
Un commento importante: questo codice deduce le colonne / intestazioni dai campi nella prima riga. Se i tuoi dati json hanno colonne "frastagliate", ad esempio diciamo che row1 abbia 5 colonne ma row2 abbia 6 colonne, allora devi fare un primo passaggio sui dati per ottenere il set totale di tutte le colonne e usarlo come intestazioni.
Mike Repass,

Con i dati che ho avuto questa è stata una grande parte della soluzione di cui avevo bisogno, dal momento che il mio JSON non era frastagliato, ha funzionato meravigliosamente con alcune lievi modifiche per l'output poiché lo stavo eseguendo all'interno di uno script esistente.
MichaelF,

1
Questo codice presuppone inoltre che i valori verranno emessi nello stesso ordine delle chiavi nella riga di intestazione. Sebbene ciò possa aver funzionato per fortuna, non è affatto garantito.
RyanHennig,

Ottenere errore di codifica. Qualche idea su come aggiungere la codifica a utf-8?
Elad Tabak,

25

Questo codice dovrebbe funzionare per te, supponendo che i tuoi dati JSON siano in un file chiamato data.json.

import json
import csv

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

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

1
Hmmm, no - csv_file.writerow( f.writerowovviamente non c'è , suppongo che tu abbia fatto un refuso lì!) Vuole una sequenza, non un dict - e nel tuo esempio, ogni elemento è un dict. Questo funzionerebbe per il caso speciale ALTRI, come ho identificato nella mia risposta - in cui il file JSON ha una matrice di matrici; non funziona per una serie di oggetti, che è il caso speciale che sembra stia cercando di risolvere (quello richiede uno csv.DictWriter- e ovviamente è necessario estrarre i nomi dei campi e decidere un ordine per istanziarlo ! -).
Alex Martelli,

@DanLoewenherz Non funziona con le recenti versioni di Python. TypeError: può solo concatenare l'elenco (non "dict_values") da elencare
Apolo Radomer

18

Sarà facile da usare csv.DictWriter(), l'implementazione dettagliata può essere così:

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

Si noti che ciò presuppone che tutti gli oggetti JSON abbiano gli stessi campi.

Ecco il riferimento che può aiutarti.


Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
Mathieu,

3
@purplepsycho Ho trovato questa risposta con un voto negativo, che meritava di essere solo link. Il nuovo utente, che potrebbe non essere a conoscenza del solo collegamento non è una buona risposta, lo ha corretto. Ho votato; forse potresti farlo anche tu, per incoraggiare il nuovo utente a continuare a partecipare alla nostra community?
Mawg dice di reintegrare Monica il

6

Ho avuto problemi con la soluzione proposta da Dan , ma questo ha funzionato per me:

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

Dove "test.json" conteneva quanto segue:

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

Si è verificato un errore durante il tentativo del programma sui dati di esempio C: \ curl> python json2csv.py Traceback (ultima chiamata più recente): file "json2csv.py", riga 11, in <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. valori ()) TypeError: può solo concatenare l'elenco (non "dict_values") da elencare
Mian Asbat Ahmad,

Ho provato di nuovo proprio ora in Python 2.7.9 e funziona bene per me.
Amanda,

6

Utilizzare json_normalizeda pandas:

  • Dati i dati forniti, in un file denominato test.json
  • encoding='utf-8' potrebbe non essere necessario.
  • Il seguente codice sfrutta la pathliblibreria
    • .open è un metodo di pathlib
    • Funziona anche con percorsi non Windows
import pandas as pd
# As of Pandas 1.01, json_normalize as pandas.io.json.json_normalize is deprecated and is now exposed in the top-level namespace.
# from pandas.io.json import json_normalize
from pathlib import Path
import json

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

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

# create dataframe
df = pd.json_normalize(data)

# dataframe view
 pk            model  fields.codename           fields.name  fields.content_type
 22  auth.permission     add_logentry     Can add log entry                    8
 23  auth.permission  change_logentry  Can change log entry                    8
 24  auth.permission  delete_logentry  Can delete log entry                    8
  4  auth.permission        add_group         Can add group                    2
 10  auth.permission      add_message       Can add message                    4

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

Uscita 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

Altre risorse per oggetti JSON più nidificati:


4

Come menzionato nelle risposte precedenti, la difficoltà nel convertire json in CSV è dovuta al fatto che un file JSON può contenere dizionari nidificati e pertanto essere una struttura di dati multidimensionale rispetto a una CSV che è una struttura di dati 2D. Tuttavia, un buon modo per trasformare una struttura multidimensionale in un CSV è di avere CSV multipli che si collegano con le chiavi primarie.

Nel tuo esempio, il primo output CSV ha le colonne "pk", "modello", "campi" come colonne. I valori per "pk" e "modello" sono facili da ottenere ma poiché la colonna "campi" contiene un dizionario, dovrebbe essere il suo csv e poiché "nome in codice" sembra essere la chiave primaria, puoi usare come input per "campi" per completare il primo CSV. Il secondo CSV contiene il dizionario dalla colonna "campi" con nome in codice come chiave primaria che può essere utilizzata per legare insieme i 2 CSV.

Ecco una soluzione per il tuo file json che converte i dizionari nidificati in 2 CSV.

import csv
import json

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

    header = set()

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

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

readAndWrite("data")

4

So che è passato molto tempo da quando questa domanda è stata posta, ma ho pensato di poter aggiungere alla risposta di tutti gli altri e condividere un post sul blog che penso spieghi la soluzione in modo molto conciso.

Ecco il link

Apri un file per la scrittura

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

Crea l'oggetto writer CSV

csvwriter = csv.writer(employ_data)
count = 0
for emp in emp_data:
      if count == 0:
             header = emp.keys()
             csvwriter.writerow(header)
             count += 1
      csvwriter.writerow(emp.values())

Assicurati di chiudere il file per salvare il contenuto

employ_data.close()

3

Non è un modo molto intelligente per farlo, ma ho avuto lo stesso problema e questo ha funzionato per me:

import csv

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

new_data = []

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

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

3

La risposta di Alec è ottima, ma non funziona nel caso in cui ci siano più livelli di annidamento. Ecco una versione modificata che supporta più livelli di annidamento. Inoltre, rende i nomi delle intestazioni un po 'più belli se l'oggetto nidificato specifica già la propria chiave (ad es. Dati Firebase Analytics / BigTable / BigQuery):

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

import sys
import json
import csv
import os

import jsonlines

from orderedset import OrderedSet

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

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

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

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

  return val

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

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

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



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

2

Funziona relativamente bene. Appiattisce il json per scriverlo in un file CSV. Gli elementi nidificati sono gestiti :)

Questo è per 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)

godere.


Il file .csv non è stato generato, invece, il testo CSV è stato inviato alla console. Inoltre, json.loadsnon funzionava, l'ho fatto funzionare json.load, il che produce un oggetto elenco. Terzo, gli elementi nidificati andarono persi.
ZygD,

2

Il mio modo semplice per risolvere questo:

Crea un nuovo file Python come: json_to_csv.py

Aggiungi questo codice:

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

Dopo aver aggiunto questo codice, salva il file ed eseguilo sul terminale:

python json_to_csv.py input.txt output.csv

Spero che questo ti sia d'aiuto.

CI VEDIAMO!


1
Questo esempio funziona come un fascino! grazie per la condivisione sono stato in grado di convertire il mio file JSON in CSV usando questo script Python
Mostafa,

2

Sorprendentemente, ho scoperto che nessuna delle risposte pubblicate qui finora tratta correttamente tutti gli scenari possibili (ad es., Nidificati, elenchi nidificati, valori Nessuno, ecc.).

Questa soluzione dovrebbe funzionare in tutti gli scenari:

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

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

2

Prova questo

import csv, json, sys

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

output = csv.writer(sys.stdout)

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

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

2

Questo codice funziona per qualsiasi dato file json

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

import json
import csv

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



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

count = 0

for pt in data:

      if count == 0:

             header = pt.keys()

             csvwriter.writerow(header)

             count += 1

      csvwriter.writerow(pt.values())

pt_data1.close()

1

Modificata la risposta di Alec McGail per supportare JSON con liste all'interno

    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

Grazie!


1
import json,csv
t=''
t=(type('a'))
json_data = []
data = None
write_header = True
item_keys = []
try:
with open('kk.json') as json_file:
    json_data = json_file.read()

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

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

1

Se consideriamo l'esempio seguente per convertire il file in formato json in file formattato CSV.

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

Il codice seguente converte il file json (data3.json) in 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')])

Il codice sopra menzionato è stato eseguito nel pycharm installato localmente e ha convertito con successo il file json nel file csv. Spero che questo aiuto per convertire i file.


0

Poiché i dati sembrano essere in un formato dizionario, sembrerebbe che dovresti effettivamente usare csv.DictWriter () per produrre effettivamente le righe con le informazioni di intestazione appropriate. Ciò dovrebbe consentire una gestione più semplice della conversione. Il parametro fieldnames avrebbe quindi impostato correttamente l'ordine mentre l'output della prima riga come header avrebbe permesso che fosse letto ed elaborato in seguito da csv.DictReader ().

Ad esempio, Mike Repass ha usato

output = csv.writer(sys.stdout)

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

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

Tuttavia, basta cambiare la configurazione iniziale in output = csv.DictWriter (filesetting, fieldnames = data [0] .keys ())

Si noti che poiché l'ordine degli elementi in un dizionario non è definito, potrebbe essere necessario creare esplicitamente le voci dei nomi dei campi. Una volta che lo fai, lo scrittore funzionerà. Le scritture funzionano quindi come mostrato in origine.


0

Purtroppo non ho la reputazione di dare un piccolo contributo alla sorprendente risposta di @Alec McGail. Stavo usando Python3 e ho dovuto convertire la mappa in un elenco dopo il commento @Alexis R.

Inoltre ho scoperto che il writer CSV stava aggiungendo un CR aggiuntivo al file (ho una riga vuota per ogni riga con i dati all'interno del file CSV). La soluzione è stata molto semplice seguendo la risposta di @Jason R. Coombs a questo thread: CSV in Python aggiungendo un ritorno a capo extra

Devi semplicemente aggiungere il parametro lineterminator = '\ n' a csv.writer. Sarà:csv_w = csv.writer( out_file, lineterminator='\n' )


0

È possibile utilizzare questo codice per convertire un file json in file CSV Dopo aver letto il file, sto convertendo l'oggetto in un frame di dati Panda e quindi salvandolo in un 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)

questo non tiene conto dei sottocampi (come "campi" nell'esempio) - l'oggetto secondario si trova in una colonna invece del suo contenuto separato anche in singole colonne.
Presepio

0

Potrei essere in ritardo alla festa, ma penso di aver affrontato il problema simile. Avevo un file json che assomigliava a questo

Struttura dei file JSON

Volevo solo estrarre poche chiavi / valori da questi file json. Quindi, ho scritto il seguente codice per estrarre lo stesso.

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

Spero che questo possa aiutare. Per i dettagli su come funziona questo codice puoi controllare qui


0

Questa è una modifica della risposta di @ MikeRepass. Questa versione scrive il file CSV in un file e funziona sia per Python 2 che per 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())
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.