292 votes

convertir au format csv, json à l'aide de python

J'ai un fichier JSON que je veux pour le convertir en un fichier CSV. Comment puis-je le faire via Python?

0 vote en bas de vérifier

J'ai essayé:

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) 

f.close()

Cependant, il n'a pas de travail. Je suis à l'aide de Django et de l'erreur que j'ai reçu est:

file' object has no attribute 'writerow'

De la sorte, alors j'ai essayé le suivant:

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

J'ai ensuite le message d'erreur:

sequence expected

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

150voto

YOU Points 44812

Je ne suis pas sûr que cette question est résolue déjà ou pas, mais permettez-moi de coller ce que j'ai fait pour référence.

Tout d'abord, votre JSON a des objets imbriqués, et donc, ça ne peut pas être directement convertis au format CSV. Vous avez besoin de le changer pour quelque chose comme ceci:

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

Voici mon code pour générer CSV à partir de:

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

Vous obtiendrez en sortie:

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

41voto

Alex Martelli Points 330805

JSON peut représenter une grande variété de structures de données -- un JS "objet" est à peu près comme un Python dict (avec des clés de chaîne), un JS "tableau" à peu près comme une liste Python, et vous pouvez imbriquer aussi longtemps que la finale de "la feuille" les éléments sont des nombres ou des chaînes de caractères.

CSV peut essentiellement ne représentent qu'un 2-D de la table -- en option avec une première ligne de "en-têtes", c'est à dire, "les noms de colonnes", ce qui peut rendre la table interprétable comme une liste des dicts, au lieu de l'interprétation normale, une liste de listes (de nouveau, "feuille" éléments peuvent être des nombres ou des chaînes de caractères).

Ainsi, dans le cas général, vous ne pouvez pas traduire un arbitraire JSON structure d'un fichier CSV. Dans quelques cas spéciaux, vous pouvez (tableau de tableaux, sans plus de nidification; les tableaux d'objets qui ont tous exactement les mêmes touches). Qui cas particulier, le cas échéant, s'applique à votre problème? Les détails de la solution dépendent du cas particulier que vous avez. Étant donné le fait étonnant que vous ne mentionnent même pas qui on l'applique, je soupçonne que vous ne pouvez pas avoir considéré que la contrainte, ni utilisables cas dans la réalité s'applique, et votre problème est impossible à résoudre. Mais s'il vous plaît préciser!

37voto

Mike Repass Points 2302

Une solution générique qui traduit tout json liste de plat objets au format csv.

Passer l'entrée.fichier json comme premier argument sur la ligne de commande.

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

26voto

Dan Points 1417

Ce code devrait fonctionner pour vous, en supposant que vos données JSON est dans un fichier appelé" 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:
        csv_file.writerow([item['pk'], item['model']] + item['fields'].values())

4voto

dmathewwws Points 1

Comme mentionné dans la réponse à la question précédente la difficulté de la conversion au format csv, json est à cause d'un fichier json peuvent inclurent des dictionnaires et, par conséquent, être une structure de données multidimensionnelles versets d'un fichier csv qui est un 2D structure de données. Cependant, un bon moyen de transformer une structure multidimensionnelle csv est d'avoir plusieurs csvs en lien avec les clés primaires.

Dans votre exemple, la première sortie csv a les colonnes "pk","modèle","champs" comme vos colonnes. Valeurs de "pk", et "modèle" sont faciles à obtenir, mais parce que les "champs" de la colonne contient un dictionnaire, il doit être son propre csv et parce que "nom de code" s'affiche à l'être la clé primaire, vous pouvez l'utiliser comme entrée pour les "champs" pour terminer la première csv. La deuxième csv contient le dictionnaire de l' "champs" de la colonne avec le nom de code tant que la clé primaire qui peut être utilisé pour attacher les 2 csvs ensemble.

Voici une solution pour votre fichier json qui convertit un ensemble de dictionnaires pour 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")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X