Question

J'ai un fichier JSON que je veux convertir un fichier CSV. Comment puis-je faire avec Python?

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 ne fonctionne pas. J'utilise Django et l'erreur que j'ai reçu est:

file' object has no attribute 'writerow'

Alors, j'essayé ce qui suit:

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'obtiens alors l'erreur:

sequence expected

fichier JSON Exemple:

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

Pas de solution correcte

Autres conseils

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

D'abord, votre JSON a des objets imbriqués, de sorte qu'il ne peut normalement pas être converti directement au format CSV. Vous devez changer cela à quelque chose comme ceci:

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

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

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 comme 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

Avec la pandas , c'est aussi facile que d'utiliser deux commandes!

pandas.read_json()

Pour convertir une chaîne JSON à un objet pandas géants (soit une série ou dataframe). Ensuite, en supposant que les résultats ont été stockés comme df:

df.to_csv()

Ce qui peut soit renvoyer une chaîne ou écrire directement dans un fichier csv.

D'après la verbosité des réponses précédentes, nous devrions tous remercier pour le raccourci pandas géants.

Je suppose que votre fichier JSON décode dans une liste de dictionnaires. Nous avons d'abord besoin d'une fonction qui aplatir les objets 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

Le résultat de l'exécution cet extrait sur votre objet JSON:

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

est

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

Après avoir appliqué cette fonction à chaque dict dans le tableau d'entrée des objets JSON:

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

et trouver les noms de colonnes pertinents:

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

il est pas difficile à exécuter ce à travers le module 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 ) )

J'espère que cela aide!

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

CSV peut essentiellement représenter seulement une table 2-D - éventuellement avec une première rangée de « têtes », à savoir, « les noms de colonnes », ce qui peut rendre la table interprétable comme une liste de dicts, au lieu de l'interprétation normale, une liste de listes (encore une fois, des éléments « feuilles » peuvent être des nombres ou des chaînes).

Ainsi, dans le cas général, vous ne pouvez pas traduire une structure JSON arbitraire dans un fichier CSV. Dans quelques cas particuliers, vous pouvez (tableau de tableaux sans imbrication supplémentaire, les tableaux d'objets qui ont tous exactement les mêmes touches). Auquel 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. Compte tenu du fait étonnant que vous ne mentionnez même pas que l'on applique, je suppose que vous ne pouvez pas avoir considéré la contrainte, aucun cas utilisable applique en effet, et votre problème est impossible à résoudre. Mais s'il vous plaît ne clarifient!

Une solution générique qui se traduit par une liste de JSON de plat objets à csv.

Faire passer le fichier input.json comme premier argument de 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())

Ce code devrait travailler 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:
        fields = list(item['fields'].values())
        csv_file.writerow([item['pk'], item['model']] + fields)

Il sera facile à utiliser csv.DictWriter(), la mise en œuvre détaillée peut être comme ceci:

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

Notez que cela suppose que tous vos objets JSON ont les mêmes champs.

Voici le référence qui peut vous aider.

J'avais des problèmes avec solution de Dan proposée , mais cela a fonctionné pour moi:

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

Où "test.json" contenait ce qui suit:

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

Comme indiqué dans les réponses précédentes de la difficulté à convertir au format CSV json En effet, un fichier json peut contenir des dictionnaires imbriqués et donc être une structure de données multidimensionnelle versets CSV qui est une structure de données 2D. Cependant, une bonne façon de transformer une structure multidimensionnelle à un csv est d'avoir plusieurs CSVs qui lient avec les clés primaires.

Dans votre exemple, la première sortie csv a les colonnes « pk », « modèle », « champs » comme vos colonnes. Les valeurs de « pk » et « modèle » sont faciles à obtenir, mais parce que la colonne « champs » contient un dictionnaire, il devrait être son propre csv et parce que « nom de code » apparaît à la clé primaire, vous pouvez utiliser comme entrée pour « champs » pour compléter la première csv. Le second contient csv le dictionnaire de la colonne « champs » avec nom de code comme la clé primaire qui peut être utilisé pour lier les 2 CSVs ensemble.

Voici une solution pour votre fichier JSON qui convertit un dictionnaires imbriqués 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")

Je sais qu'il a été longtemps que cette question a été posée, mais je pensais que je pourrais ajouter à tout le monde la réponse d'un autre et de partager un blog que je pense expliquer la solution d'une manière très concise.

Voici le lien

Ouvrir un fichier pour écrire

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

Créer l'objet écrivain 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())

Assurez-vous de fermer le fichier afin de sauvegarder le contenu

employ_data.close()

Cela fonctionne relativement bien. Il aplatit le JSON de l'écrire dans un fichier csv. éléments emboîtés sont gérés:)

C'est pour 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)

profiter.

Ma façon simple de résoudre ceci:

Créer un nouveau fichier Python comme: json_to_csv.py

Ajoutez ce code:

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

Après ajouter ce code, enregistrez le fichier et exécuter au terminal:

  

python json_to_csv.py input.txt output.csv

J'espère que cela vous aide.

SeeYa!

Il n'est pas une façon très intelligente de le faire, mais je l'ai eu le même problème et cela a fonctionné pour moi:

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

modifié la réponse de Alec McGail pour soutenir JSON avec des listes à l'intérieur

    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

Merci!

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)

Essayer cette

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

Ce code fonctionne pour tout fichier JSON donné

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

réponse Alec est grande, mais il ne fonctionne pas dans le cas où il y a plusieurs niveaux d'imbrication. Voici une version modifiée qui prend en charge plusieurs niveaux d'imbrication. Il fait également les noms d'en-tête un peu plus agréable si l'objet imbriqué spécifie déjà sa propre clé (par exemple Firebase données 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)

Étant donné que les données semblent être dans un format de dictionnaire, il semblerait que vous devriez réellement utiliser csv.DictWriter () pour réellement sortir les lignes avec les informations d'en-tête approprié. Cela devrait permettre à la conversion à traiter un peu plus facile. Le paramètre fieldnames alors mis en place l'ordre correctement pendant la sortie de la première ligne comme les en-têtes lui permettrait d'être lu et traité plus tard par csv.DictReader ().

Par exemple, Mike Repass utilisé

output = csv.writer(sys.stdout)

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

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

Cependant, juste modifier la configuration initiale     output = csv.DictWriter (filesetting, fieldnames = data [0] .keys ())

Notez que depuis l'ordre des éléments dans un dictionnaire n'est pas défini, vous pourriez avoir à créer des entrées de FIELDNAMES explicitement. Une fois que vous faites cela, le writerow fonctionnera. Les écritures fonctionnent alors comme initialement indiqué.

Malheureusement, je ne l'ai pas enouthg réputation de faire une petite contribution à la réponse étonnante @Alec McGail. J'utilisais python3 et j'ai besoin de convertir la carte à une liste suivante l'@Alexis R commentaire.

Additionaly J'ai trouvé l'écrivain csv ajoutait un CR supplémentaire pour le fichier (j'ai une ligne vide pour chaque ligne avec des données à l'intérieur du fichier csv). La solution a été très facile après la réponse R. Coombs @ Jason à ce fil: CSV dans le python addition d'un retour chariot supplémentaire

Vous devez ajouter simplement le lineterminator = « \ n » paramètre à la csv.writer. Ce sera: csv_w = csv.writer( out_file, lineterminator='\n' )

Étonnamment, je trouve que aucune des réponses affichées ici si bien traiter correctement tous les scénarios possibles (par exemple, dicts imbriquées, listes imbriquées, les valeurs Aucun, etc.).

Cette solution devrait fonctionner dans tous les scénarios:

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

Vous pouvez utiliser ce code pour convertir un fichier JSON fichier csv Après avoir lu le dossier, je suis en train de convertir l'objet de pandas géants dataframe et puis enregistrez à un fichier 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)

Je pourrais être en retard à la fête, mais je pense, je l'ai traité le même problème. J'ai eu un fichier JSON qui ressemblait à ceci

Je ne voulais extraire quelques clés / valeurs de ces fichiers JSON. Alors, je l'ai écrit le code suivant pour en extraire le même.

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

J'espère que cela vous aidera. Pour plus de détails sur la façon dont ce travail de code que vous pouvez vérifier

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top