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

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)

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

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!
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())
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)
- 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.
Un enfoque simple para esto es usar
jq
como 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.
Feb 10, 2021 at 1:55
try: jsoncsv and/or libjson2csv.
Feb 10, 2021 at 2:12
Use the JSON to CSV API at www.convertcsv.io Just tried, worked great with your data.
Nov 6, 2021 at 23:24