¿Cómo puedo convertir JSON a CSV?

10 minutos de lectura

¿Como puedo convertir JSON a CSV
pez pequeño

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 me sale el error:

`sequence expected`

Ejemplo de archivo 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
        }
    }
]

  • Un enfoque simple para esto es usar jqcomo se describe aquí: stackoverflow.com/questions/32960857/…

    – Micah Elliott

    11 de junio de 2018 a las 21:02

  • 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.

    – Hombre de la pila

    11 de junio de 2019 a las 7:04


  • Escribí un código js simple que se enfoca solo en el tipo de estructura de matriz json en github [github.com/fromdev/tools/blob/master/… that is running here tools.fromdev.com/json-to-csv-converter.html – as other answers suggest – the conversion may not always be possible. So guessing it is an array or list json.

    – software.wikipedia

    Feb 10, 2021 at 1:55


  • try: jsoncsv and/or libjson2csv.

    – Milovan Tomašević

    Feb 10, 2021 at 2:12


  • Use the JSON to CSV API at www.convertcsv.io Just tried, worked great with your data.

    – dataman

    Nov 6, 2021 at 23:24

1646968928 92 ¿Como puedo convertir JSON a CSV
vmg

With the pandas library, this is as easy as using two commands!

df = pd.read_json()

read_json converts a JSON string to a pandas object (either a series or dataframe). Then:

df.to_csv()

Which can either return a string or write directly to a csv-file. See the docs for to_csv.

Based on the verbosity of previous answers, we should all thank pandas for the shortcut.

For unstructured JSON see this answer.

EDIT:
Someone asked for a working minimal example:

import pandas as pd

with open('jsonfile.json', encoding='utf-8') as inputfile:
    df = pd.read_json(inputfile)

df.to_csv('csvfile.csv', encoding='utf-8', index=False)

  • The provided code snippets are confusing, since pd.read_json() does not provide any input json file or json string. Can we edit this answer to provide a working minimal example?

    – 6005

    Oct 14, 2021 at 16:49


1646968928 749 ¿Como puedo convertir JSON a CSV
YOU

First, your JSON has nested objects, so it normally cannot be directly converted to CSV. You need to change that to something like this:

{
    "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á una 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

  • esto es trabajo, pero lo siento antes, ¿puedo obtener algo que no sea un código duro? Lo creo mejor. Puedo usar f.writerow (a) y la a es una variable que declaro antes, gracias antes.

    – pez pequeño

    9 de diciembre de 2009 a las 8:16

  • Para mí esto funciona casi a la perfección. En el CSV exportado, algunos de los campos están rodeados por [u' and ']. ¿Cuál es la solución alternativa (sin posprocesamiento)? si hay uno… 🙂

    – Dror

    10 de julio de 2014 a las 12:20

  • A continuación, muestro una forma de hacerlo de manera más general, sin tener que codificarlo.

    – Alec McGail

    26 ago 2015 a las 21:11

  • hey, he intentado esto pero estoy recibiendo un TypeError: a bytes-like object is required, not 'str' en f.writerow(['pk', 'model', 'codename', 'name', 'content_type'])

    – Aditya Hariharan

    7 de marzo de 2017 a las 9:31

  • para python3 cambie la línea con la apertura del archivo csv a f = csv.writer(open("test.csv", "w", newline=''))

    – PiotrK

    14 de abril de 2019 a las 12:15


1646968929 470 ¿Como puedo convertir JSON a CSV
alec mcgail

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

  • ¿Cómo manejará las listas/colecciones anidadas?

    – Wojciech Jakubas

    22 de febrero a las 11:49

  • Es recursivo, por lo que debería funcionar bien. ¡Sin embargo, tendrá que ser modificado para las listas!

    – Alec McGail

    23 de febrero a las 14:40

JSON puede representar una amplia variedad de estructuras de datos: un “objeto” JS es más o menos como un dictado de Python (con claves de cadena), una “matriz” JS más o menos como una lista de Python, y puede anidarlos siempre que el “final” 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”, lo que puede hacer que la tabla sea interpretable como una lista de dictados, en lugar de la interpretación normal, una lista de listas (nuevamente, 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 más anidamiento; matrices de objetos que tienen exactamente las mismas claves). ¿Qué caso especial, si alguno, se aplica a su problema? Los detalles de la solución dependen del caso especial que tenga. Dado el hecho asombroso de que ni siquiera menciona cuál se aplica, sospecho que es posible que no haya considerado la restricción, ni el caso utilizable se aplica, y su problema es imposible de resolver. ¡Pero por favor aclara!

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

Pase el archivo input.json como primer argumento en la línea de comandos.

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

  • 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 la fila 1 tiene 5 columnas pero la fila 2 tiene 6 columnas, entonces debe pasar primero por los datos para obtener el conjunto total de todas las columnas y usar eso como encabezados.

    – Mike Repass

    7 dic 2012 a las 21:59

  • Con los datos que tenía, esta era una gran parte de la solución que necesitaba, dado que mi JSON no estaba irregular, funcionó maravillosamente con algunos ajustes leves para la salida ya que estaba ejecutando esto dentro de un script existente.

    – Michael F.

    24/04/2014 a las 15:00

  • Este código también asume 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.

    – Ryan Hennig

    28 de julio de 2015 a las 19:09

  • Obteniendo error de codificación. ¿Alguna idea de cómo agregar codificación a utf-8?

    – Elad Tabak

    7 de abril de 2016 a las 9:34

Este código debería funcionar para usted, asumiendo 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)

  • 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 la fila 1 tiene 5 columnas pero la fila 2 tiene 6 columnas, entonces debe pasar primero por los datos para obtener el conjunto total de todas las columnas y usar eso como encabezados.

    – Mike Repass

    7 dic 2012 a las 21:59

  • Con los datos que tenía, esta era una gran parte de la solución que necesitaba, dado que mi JSON no estaba irregular, funcionó maravillosamente con algunos ajustes leves para la salida ya que estaba ejecutando esto dentro de un script existente.

    – Michael F.

    24/04/2014 a las 15:00

  • Este código también asume 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.

    – Ryan Hennig

    28 de julio de 2015 a las 19:09

  • Obteniendo error de codificación. ¿Alguna idea de cómo agregar codificación a utf-8?

    – Elad Tabak

    7 de abril de 2016 a las 9:34

Utilizar json_normalize desde pandas:

  • Usando los datos de muestra del OP en un archivo llamado test.json.
  • encoding='utf-8' se ha utilizado aquí, pero puede no ser necesario para otros casos.
  • El siguiente código aprovecha la pathlib Biblioteca.
    • .open es un método de pathlib.
    • También funciona con rutas que no son de Windows.
  • Utilizar pandas.to_csv(...) para guardar los datos en un archivo csv.
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

Recursos para objetos JSON más anidados:

  • SO Respuestas:
    • Aplanar una matriz JSON con python
    • ¿Cómo aplanar JSON anidado recursivamente, con flatten_json?
    • Cómo json_normalize una columna con NaNs
    • Dividir / Explotar una columna de diccionarios en columnas separadas con pandas
    • Ver el json_normalize etiqueta para otras preguntas relacionadas.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad