¿Cómo puedo convertir JSON a CSV?

184

Tengo un archivo JSON que quiero convertir a un archivo CSV. ¿Cómo puedo hacer esto con Python?

Lo intenté:

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

Sin embargo, no funcionó. Estoy usando Django y el error que recibí es:

file' object has no attribute 'writerow'

Luego probé lo siguiente:

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

Entonces recibo el error:

sequence expected

Archivo json de muestra:

[{
        "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
        }
    }
]
pez pequeño
fuente
1
csv_file.writerow (item) requiere que el ítem sea una simple lista de cadenas o números. Intente convertir cada objeto json en una lista plana, como {"pk": 22, "model": "auth.permission"} se convertiría en [22, auth.permission].
Suppressingfire
1
Un enfoque simple para esto es utilizar jq, como se describe aquí: stackoverflow.com/questions/32960857/…
Micah Elliott
Alternativa de terceros: json-csv.com (para conversiones únicas ) o json-csv.com/api para automatizar con Python. Esta es una solución simple para estructuras JSON más complejas.
Stack Man

Respuestas:

129

Primero, su JSON tiene objetos anidados, por lo que normalmente no se puede convertir directamente a CSV. Necesitas cambiar eso a algo como esto:

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

Aquí está mi código para generar CSV a partir de eso:

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

Obtendrá salida como:

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

fuente
2
este es un trabajo, pero lo siento antes de que puedo conseguir algo que no dura lo código que mejor Identificación del i puede utilizar f.writerow (a) y el de una cierta variabel que yo declaro antes, gracias antes
little_fish
Para mí esto funciona casi a la perfección. En el CSV exportado, algunos de los campos están rodeados por [u'y ']. ¿Cuál es la solución alternativa (sin procesamiento posterior)? si hay uno ... :)
Dror
3
A continuación, he mostrado una forma de hacerlo de manera más general, sin tener que codificarlo
Alec McGail
44
Hey, yo he intentado esto, pero yo estoy un TypeError: a bytes-like object is required, not 'str'enf.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Aditya Hariharan
8
para cambiar la línea python3 con la apertura de un archivo CSV af = csv.writer(open("test.csv", "w", newline=''))
PiotrK
119

¡Con la pandas biblioteca , esto es tan fácil como usar dos comandos!

pandas.read_json()

Para convertir una cadena JSON en un objeto pandas (ya sea una serie o un marco de datos). Luego, suponiendo que los resultados se almacenaron como df:

df.to_csv()

Que puede devolver una cadena o escribir directamente en un archivo csv.

Según la verbosidad de las respuestas anteriores, todos deberíamos agradecer a los pandas por el acceso directo.

vmg
fuente
1
Esta es una respuesta fantástica (+1), tan simple y .to_csv()realmente potente (por ejemplo, filtrado de columnas gratuito). Necesito aprender pandas.
WoJ
3
Como se señaló, esta respuesta no funciona para los datos en esta pregunta. orient='records'debe establecerse, pero cada fila fieldsseguirá siendo un dict, que no es lo que solicitó el OP.
Trenton McKinney el
90

Supongo que su archivo JSON se decodificará en una lista de diccionarios. Primero necesitamos una función que aplanará los objetos 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

El resultado de ejecutar este fragmento en su objeto JSON:

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

es

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

Después de aplicar esta función a cada dict en la matriz de entrada de objetos JSON:

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

y encontrar los nombres de columna relevantes:

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

No es difícil ejecutar esto a través del módulo 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 ) )

¡Espero que esto ayude!

Alec McGail
fuente
Usando Python 3.6, tuve que hacer una lista del JSON aplanado para que el último bucle funcionara: "input = list (map (lambda x: flattenjson (x," __ "), input))". Sin embargo, no entiendo por qué lo iterable no es suficiente. También tuve que especificar la codificación al abrir el archivo de salida ya que mis datos usan UTF8. Definitivamente ayudó, ¡gracias!
Alexis R
Esto es genial, gracias Alec! Lo modifiqué para que funcione con múltiples niveles de anidamiento: stackoverflow.com/a/57228641/473201
phreakhead el
35

JSON puede representar una amplia variedad de estructuras de datos: un "objeto" JS es más o menos como un dict Python (con teclas de cadena), una "matriz" JS más o menos como una lista de Python, y puede anidarlos siempre que el "final" los elementos "hoja" son números o cadenas.

CSV puede representar esencialmente solo una tabla 2-D, opcionalmente con una primera fila de "encabezados", es decir, "nombres de columna", que pueden hacer que la tabla sea interpretable como una lista de dictados, en lugar de la interpretación normal, una lista de listas (de nuevo, los elementos "hoja" pueden ser números o cadenas).

Entonces, en el caso general, no puede traducir una estructura JSON arbitraria a un CSV. En algunos casos especiales puede (matriz de matrices sin anidamiento adicional; matrices de objetos que tienen exactamente las mismas claves). ¿Qué caso especial, si corresponde, se aplica a su problema? Los detalles de la solución dependen del caso especial que tenga. Dado el hecho sorprendente de que ni siquiera menciona cuál aplica, sospecho que puede que no haya considerado la restricción, de hecho, ninguno de los casos utilizables se aplica y su problema es imposible de resolver. Pero por favor aclarar!

Alex Martelli
fuente
31

Una solución genérica que traduce cualquier lista json de objetos planos a csv.

Pase el archivo input.json como primer argumento en la línea de 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())
Mike Repass
fuente
2
Un comentario importante: este código infiere las columnas / encabezados de los campos en la primera fila. Si sus datos json tienen columnas 'irregulares', es decir, digamos que row1 tiene 5 columnas pero row2 tiene 6 columnas, entonces debe hacer un primer pase sobre los datos para obtener el conjunto total de todas las columnas y usarlo como encabezado.
Mike Repass
Con los datos que tenía, esta era una gran parte de la solución que necesitaba, ya que mi JSON no era irregular, funcionó maravillosamente con algunos pequeños ajustes para la salida ya que estaba ejecutando esto dentro de un script existente.
MichaelF
1
Este código también supone que los valores se generarán en el mismo orden que las claves en la fila del encabezado. Si bien eso puede haber funcionado por suerte, de ninguna manera está garantizado.
RyanHennig
Obteniendo error de codificación. ¿Alguna idea de cómo agregar codificación a utf-8?
Elad Tabak
25

Este código debería funcionar para usted, suponiendo que sus datos JSON estén en un archivo llamado 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
fuente
1
Hmmm, no, csv_file.writerow(no hay, f.writerowpor supuesto, ¡supongo que cometiste un error tipográfico allí!) Quiere una secuencia, no un dict, y en tu ejemplo, cada elemento es un dict. Esto funcionaría para el OTRO caso especial, como identifiqué en mi respuesta, donde el archivo JSON tiene una matriz de matrices; no funciona para una variedad de objetos, que es el caso especial que parece estar tratando de resolver (eso requiere un csv.DictWriter- y, por supuesto, necesita extraer los nombres de campo y decidir un orden para instanciarlo ! -).
Alex Martelli
@DanLoewenherz Eso no funciona en versiones recientes de Python. TypeError: solo puede concatenar la lista (no "dict_values") a la lista
Apolo Radomer
18

Será fácil de usar csv.DictWriter(), la implementación detallada puede ser así:

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

Tenga en cuenta que esto supone que todos sus objetos JSON tienen los mismos campos.

Aquí está la referencia que puede ayudarlo.

ReturnHttp402
fuente
Si bien este enlace puede responder la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden volverse inválidas si la página vinculada cambia. - De la opinión
Mathieu
3
@purplepsycho Encontré esta respuesta con un voto negativo, que merecía ser solo un enlace. El nuevo usuario, que podría haber ignorado que el enlace solo no es una buena respuesta, lo ha corregido. He votado ¿quizás usted también podría alentar al nuevo usuario a continuar participando en nuestra comunidad?
Mawg dice que reinstale a Mónica el
6

Estaba teniendo problemas con la solución propuesta de Dan , pero esto funcionó para mí:

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

Donde "test.json" contenía lo siguiente:

[ 
{"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
fuente
Se produjo un error al probar el programa en los datos de muestra C: \ curl> python json2csv.py Traceback (última llamada reciente): archivo "json2csv.py", línea 11, en <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. values ​​()) TypeError: solo puede concatenar la lista (no "dict_values") para listar
Mian Asbat Ahmad
Lo intenté nuevamente en Python 2.7.9 y funciona bien para mí.
Amanda
6

Uso json_normalizede pandas:

  • Dados los datos proporcionados, en un archivo llamado test.json
  • encoding='utf-8' puede no ser necesario
  • El siguiente código aprovecha la pathlibbiblioteca
    • .open es un método de pathlib
    • Funciona también con rutas que no son de 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')

Salida 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

Otros recursos para objetos JSON más anidados:

Trenton McKinney
fuente
4

Como se mencionó en las respuestas anteriores, la dificultad para convertir json a csv se debe a que un archivo json puede contener diccionarios anidados y, por lo tanto, ser una estructura de datos multidimensional frente a un csv que es una estructura de datos 2D. Sin embargo, una buena manera de convertir una estructura multidimensional en un csv es tener múltiples csvs que se unan con las claves primarias.

En su ejemplo, la primera salida de csv tiene las columnas "pk", "model", "fields" como sus columnas. Los valores para "pk" y "model" son fáciles de obtener, pero debido a que la columna "fields" contiene un diccionario, debe ser su propio csv y porque "codename" parece ser la clave principal, puede usarlo como entrada para "campos" para completar el primer csv. El segundo csv contiene el diccionario de la columna "campos" con el nombre en clave como la clave principal que se puede usar para unir los 2 csvs.

Aquí hay una solución para su archivo json que convierte un diccionario anidado a 2 csvs.

import csv
import json

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

    header = set()

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

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

readAndWrite("data")
dmathewwws
fuente
4

Sé que ha pasado mucho tiempo desde que se hizo esta pregunta, pero pensé que podría agregar a la respuesta de todos los demás y compartir una publicación de blog que creo que explica la solución de una manera muy concisa.

Aqui esta el enlace

Abrir un archivo para escribir

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

Crear el objeto escritor 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())

Asegúrese de cerrar el archivo para guardar el contenido

employ_data.close()
usuario3768804
fuente
3

No es una forma muy inteligente de hacerlo, pero he tenido el mismo problema y esto funcionó para mí:

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
fuente
3

La respuesta de Alec es excelente, pero no funciona en el caso de que haya múltiples niveles de anidamiento. Aquí hay una versión modificada que admite múltiples niveles de anidamiento. También hace que los nombres de encabezado sean un poco más agradables si el objeto anidado ya especifica su propia clave (por ejemplo, datos de 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)
phreakhead
fuente
2

Esto funciona relativamente bien. Aplana el json para escribirlo en un archivo csv. Los elementos anidados se gestionan :)

Eso es para 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)

disfrutar.

Loïc
fuente
No se generó el archivo .csv, en su lugar, se envió el texto csv a la consola. Además, json.loadsno funcionaba, lo hice funcionar json.load, lo que muy bien produce un objeto de lista. Tercero, se perdieron elementos anidados.
ZygD
2

Mi forma simple de resolver esto:

Cree un nuevo archivo Python como: json_to_csv.py

Agrega este código:

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

Después de agregar este código, guarde el archivo y ejecútelo en la terminal:

python json_to_csv.py input.txt output.csv

Espero que esto te ayude.

¡NOS VEMOS!

Gabriel Pires
fuente
1
¡Esta muestra funciona a las mil maravillas! gracias por compartir pude convertir mi archivo json en CSV usando este script de python
Mostafa
2

Sorprendentemente, descubrí que ninguna de las respuestas publicadas aquí hasta ahora trata correctamente todos los escenarios posibles (por ejemplo, dictados anidados, listas anidadas, valores de Ninguno, etc.).

Esta solución debería funcionar en todos los escenarios:

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
fuente
2

Prueba esto

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
fuente
2

Este código funciona para cualquier archivo json dado

# -*- 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
fuente
1

Se modificó la respuesta de Alec McGail para admitir JSON con listas dentro

    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

¡Gracias!

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

Si consideramos el siguiente ejemplo para convertir el archivo de formato json a un archivo con formato csv.

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

El siguiente código convertirá el archivo json (data3.json) a un archivo 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')])

El código mencionado anteriormente se ha ejecutado en el pycharm instalado localmente y ha convertido con éxito el archivo json al archivo csv. Espero que esto ayude a convertir los archivos.

SABYASACHI SAHA
fuente
0

Dado que los datos parecen estar en formato de diccionario, parecería que debería usar csv.DictWriter () para generar las líneas con la información de encabezado adecuada. Esto debería permitir que la conversión se maneje algo más fácil. El parámetro de los nombres de campo configuraría el orden correctamente mientras que la salida de la primera línea como encabezados permitiría que csv.DictReader () leyera y procesara más tarde.

Por ejemplo, Mike Repass utilizó

output = csv.writer(sys.stdout)

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

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

Sin embargo, simplemente cambie la configuración inicial a output = csv.DictWriter (configuración de archivos, nombres de campo = datos [0] .keys ())

Tenga en cuenta que dado que el orden de los elementos en un diccionario no está definido, es posible que tenga que crear entradas de nombres de campo explícitamente. Una vez que hagas eso, el escritor funcionará. Las escrituras funcionan entonces como se muestra originalmente.

sabbahillel
fuente
0

Desafortunadamente, no tengo suficiente reputación para hacer una pequeña contribución a la sorprendente respuesta de @Alec McGail. Estaba usando Python3 y he necesitado convertir el mapa a una lista después del comentario de @Alexis R.

Además, he encontrado que el escritor csv estaba agregando un CR adicional al archivo (tengo una línea vacía para cada línea con datos dentro del archivo csv). La solución fue muy fácil siguiendo la respuesta de @Jason R. Coombs a este hilo: CSV en Python agregando un retorno de carro adicional

Simplemente debe agregar el parámetro lineterminator = '\ n' al csv.writer. Será:csv_w = csv.writer( out_file, lineterminator='\n' )

derwyddon
fuente
0

Puede usar este código para convertir un archivo json en un archivo csv Después de leer el archivo, estoy convirtiendo el objeto en un marco de datos de pandas y luego lo guardo en un archivo CSV

import os
import pandas as pd
import json
import numpy as np

data = []
os.chdir('D:\\Your_directory\\folder')
with open('file_name.json', encoding="utf8") as data_file:    
     for line in data_file:
        data.append(json.loads(line))

dataframe = pd.DataFrame(data)        
## Saving the dataframe to a csv file
dataframe.to_csv("filename.csv", encoding='utf-8',index= False)
Terminator17
fuente
esto no tiene en cuenta los subcampos (como los "campos" en el ejemplo): el subobjeto está en una columna en lugar de su contenido separado en columnas individuales también.
Cribber
0

Puede que llegue tarde a la fiesta, pero creo que me he ocupado del problema similar. Tenía un archivo json que se veía así

Estructura de archivo JSON

Solo quería extraer algunas claves / valores de estos archivos json. Entonces, escribí el siguiente código para extraer el mismo.

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

Espero que esto sea de ayuda. Para obtener detalles sobre cómo funciona este código, puede consultar aquí

Udit Hari Vashisht
fuente
0

Esta es una modificación de la respuesta de @ MikeRepass. Esta versión escribe el CSV en un archivo y funciona tanto para Python 2 como para 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
fuente