Como posso converter JSON para CSV?

184

Eu tenho um arquivo JSON que desejo converter para um arquivo CSV. Como posso fazer isso com o Python?

Eu tentei:

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

No entanto, não funcionou. Estou usando o Django e o erro que recebi é:

file' object has no attribute 'writerow'

Eu tentei o seguinte:

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

Eu recebo o erro:

sequence expected

Arquivo json de amostra:

[{
        "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
        }
    }
]
peixinho
fonte
1
csv_file.writerow (item) requer que o item seja uma lista simples de cadeias ou números. Tente converter cada objeto json em uma lista simples, como {"pk": 22, "model": "auth.permission"} se tornaria [22, auth.permission].
Suprpressingfire
1
Uma abordagem simples para isso é usar jq, conforme descrito aqui: stackoverflow.com/questions/32960857/…
Micah Elliott
Alternativa de terceiros: json-csv.com (para conversões únicas) ou json-csv.com/api para automatizar com o Python. Esta é uma solução simples para estruturas JSON mais complexas.
Homem Stack

Respostas:

129

Primeiro, seu JSON possui objetos aninhados, portanto, normalmente não pode ser convertido diretamente em CSV. Você precisa mudar isso para algo assim:

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

Aqui está o meu código para gerar CSV a partir disso:

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

Você obterá a saída 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
VOCÊS
fonte
2
este é um trabalho, mas lamentamos antes que eu possa obter algo que não é difícil de código i coisa melhor id i pode usar f.writerow (a) e a uma alguma variabel que eu declarar antes de graças antes
little_fish
Para mim, isso funciona quase perfeitamente. No CSV exportado, alguns dos campos são cercados por [u'e ']. Qual é a solução alternativa (sem pós-processamento)? se houver um ... :)
Dror
3
Abaixo eu mostrei uma maneira de fazê-lo de modo mais geral, sem ter que duro-código
Alec McGail
4
hey, eu tentei isso, mas eu estou ficando um TypeError: a bytes-like object is required, not 'str'nof.writerow(['pk', 'model', 'codename', 'name', 'content_type'])
Aditya Hariharan
8
para a linha mudança python3 com a abertura de arquivo CSV paraf = csv.writer(open("test.csv", "w", newline=''))
PiotrK
118

Com a pandas biblioteca , isso é tão fácil quanto usar dois comandos!

pandas.read_json()

Para converter uma sequência JSON em um objeto pandas (uma série ou um quadro de dados). Então, assumindo que os resultados foram armazenados como df:

df.to_csv()

O que pode retornar uma string ou gravar diretamente em um arquivo csv.

Com base na verbosidade das respostas anteriores, todos devemos agradecer aos pandas pelo atalho.

vmg
fonte
1
Esta é uma resposta fantástica (+1) - tão simples e .to_csv()realmente poderosa (filtragem de colunas gratuitamente, por exemplo). Eu preciso aprender pandas.
woj
3
Como apontado, esta resposta não funciona para os dados nesta pergunta. orient='records'deve ser definido, mas cada linha de fieldsainda será um dict, que não é o que o OP solicitou.
Trenton McKinney
90

Estou assumindo que seu arquivo JSON será decodificado em uma lista de dicionários. Primeiro, precisamos de uma função que achatará os 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

O resultado da execução desse trecho no seu objeto JSON:

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

é

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

Depois de aplicar esta função a cada ditado na matriz de entrada dos objetos JSON:

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

e localizando os nomes das colunas relevantes:

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

não é difícil executar isso através do 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 ) )

Eu espero que isso ajude!

Alec McGail
fonte
Usando o Python 3.6, tive que fazer uma lista do JSON achatado para que o último loop funcionasse: "input = list (map (lambda x: flattenjson (x," __ "), input))". Eu não entendo por que o iterável não é suficiente. Eu também tive que especificar a codificação ao abrir o arquivo de saída, pois meus dados usam UTF8. Definitivamente ajudou, obrigado !!
Alexis R #
Isso é ótimo, obrigado Alec! I modificado para trabalhar com vários níveis de aninhamento: stackoverflow.com/a/57228641/473201
phreakhead
35

O JSON pode representar uma ampla variedade de estruturas de dados - um "objeto" JS é mais ou menos como um ditado Python (com chaves de seqüência de caracteres), um "array" JS mais ou menos como uma lista Python, e você pode aninha-los enquanto for final " elementos "leaf" são números ou strings.

O CSV pode essencialmente representar apenas uma tabela 2D - opcionalmente com uma primeira linha de "cabeçalhos", ou seja, "nomes de colunas", que podem tornar a tabela interpretável como uma lista de dictos, em vez da interpretação normal, uma lista de listas (novamente, os elementos "folha" podem ser números ou cadeias).

Portanto, no caso geral, você não pode converter uma estrutura JSON arbitrária em um CSV. Em alguns casos especiais, é possível (matriz de matrizes sem aninhamento adicional; matrizes de objetos com todas exatamente as mesmas chaves). Qual caso especial, se houver, se aplica ao seu problema? Os detalhes da solução dependem de qual caso especial você possui. Dado o fato surpreendente de você nem mencionar qual deles se aplica, suspeito que você não tenha considerado a restrição, nenhum caso utilizável de fato se aplica e seu problema é impossível de resolver. Mas, por favor, esclareça!

Alex Martelli
fonte
31

Uma solução genérica que converte qualquer lista json de objetos simples em csv.

Passe o arquivo input.json como primeiro argumento na linha 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())
Mike Repass
fonte
2
Um comentário importante - esse código infere as colunas / cabeçalhos dos campos na primeira linha. Se seus dados json tiverem colunas 'irregulares', ou seja, digamos que a linha1 tenha 5 colunas, mas a linha2 tenha 6 colunas, será necessário fazer uma primeira passagem sobre os dados para obter o conjunto total de todas as colunas e usá-lo como cabeçalho.
Mike Repasse
Com os dados que eu tinha, essa era uma grande parte da solução de que eu precisava, pois meu JSON não era irregular. Ele funcionou maravilhosamente com alguns ajustes leves na saída, pois eu o executava dentro de um script existente.
24514 MichaelF
1
Este código também pressupõe que os valores serão gerados na mesma ordem que as chaves na linha do cabeçalho. Embora isso possa ter funcionado por sorte, não é de forma alguma garantido.
RyanHennig
Obtendo erro de codificação. Alguma idéia de como adicionar codificação ao utf-8?
Elad Tabak #
25

Este código deve funcionar para você, assumindo que os seus dados JSON é em um arquivo chamado 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
fonte
1
Hmmm, não - csv_file.writerow( f.writerowclaro que não, suponho que você cometeu um erro de digitação lá!) Quer uma sequência, não um ditado - e no seu exemplo, cada item é um ditado. Isso funcionaria para o caso especial OTHER, como identifiquei na minha resposta - onde o arquivo JSON tem uma matriz de matrizes; ele não funciona para uma variedade de objetos, que é o caso especial que você parece estar tentando resolver (esse requer um csv.DictWriter- e, é claro, você precisa extrair os nomes dos campos e decidir sobre um pedido para instancia-lo ! -).
Alex Martelli
@ DanLoewenherz Isso não funciona nas versões recentes do Python. TypeError: pode concatenar apenas a lista (não "dict_values") para listar
Apolo Radomer
18

Será fácil de usar csv.DictWriter(), a implementação detalhada pode ser assim:

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

Observe que isso pressupõe que todos os seus objetos JSON tenham os mesmos campos.

Aqui está a referência que pode ajudá-lo.

ReturnHttp402
fonte
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada. - Do comentário
Mathieu
3
@purplepsycho Encontrei esta resposta com um voto negativo, que era merecido por ser apenas um link. O novo usuário, que pode não estar ciente de que o link apenas não é uma boa resposta, corrigiu isso. Eu votei; talvez você também possa, para incentivar o novo usuário a continuar participando da nossa comunidade?
Mawg diz que restabelece Monica
6

Eu estava tendo problemas com a solução proposta por Dan , mas isso funcionou para mim:

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

Onde "test.json" continha o seguinte:

[ 
{"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
fonte
Erro ao tentar seu programa nos dados de amostra C: \ curl> python json2csv.py Traceback (última chamada mais recente): Arquivo "json2csv.py", linha 11, em <module> f.writerow ([item ['pk '], item [' model ']] + item [' fields ']. values ​​()) TypeError: só pode concatenar a lista (não "dict_values") para listar
Mian Asbat Ahmad
Tentei novamente agora no Python 2.7.9 e funciona bem para mim.
101515 Amanda
6

Use json_normalizede pandas:

  • Dados os dados fornecidos, em um arquivo chamado test.json
  • encoding='utf-8' pode não ser necessário.
  • O código a seguir aproveita a pathlibbiblioteca
    • .open é um método de pathlib
    • Também funciona com caminhos não 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')

Saída 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

Outros recursos para objetos JSON mais aninhados:

Trenton McKinney
fonte
4

Como mencionado nas respostas anteriores, a dificuldade em converter json para csv é porque um arquivo json pode conter dicionários aninhados e, portanto, é uma estrutura de dados multidimensional versus um csv que é uma estrutura de dados 2D. No entanto, uma boa maneira de transformar uma estrutura multidimensional em um CSV é ter vários CSVs vinculados às chaves primárias.

No seu exemplo, a primeira saída csv possui as colunas "pk", "model", "fields" como suas colunas. Os valores para "pk" e "model" são fáceis de obter, mas como a coluna "fields" contém um dicionário, ele deve ser seu próprio csv e como "codename" parece ser a chave principal, você pode usar como entrada para "campos" para concluir o primeiro csv. O segundo csv contém o dicionário da coluna "fields" com o codinome como a chave primária que pode ser usada para vincular os 2 csvs.

Aqui está uma solução para o seu arquivo json que converte dicionários aninhados em 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
fonte
4

Sei que já faz muito tempo desde que essa pergunta foi feita, mas achei que poderia acrescentar à resposta de todos os outros e compartilhar um post do blog que, em minha opinião, explica a solução de uma maneira muito concisa.

Aqui está o link

Abra um arquivo para gravação

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

Crie o objeto gravador 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())

Certifique-se de fechar o arquivo para salvar o conteúdo

employ_data.close()
user3768804
fonte
3

Não é uma maneira muito inteligente de fazer isso, mas tive o mesmo problema e isso funcionou para mim:

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

A resposta de Alec é ótima, mas não funciona no caso em que há vários níveis de aninhamento. Aqui está uma versão modificada que suporta vários níveis de aninhamento. Também torna os nomes dos cabeçalhos um pouco mais agradáveis ​​se o objeto aninhado já especificar sua própria chave (por exemplo, dados do 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
fonte
2

Isso funciona relativamente bem. Nivela o json para gravá-lo em um arquivo csv. Elementos aninhados são gerenciados :)

Isso é 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)

desfrutar.

Loïc
fonte
O arquivo .csv não foi gerado, em vez disso, o texto csv foi enviado para o console. Além disso, json.loadsnão estava funcionando, eu fiz funcionar json.load, o que produz um objeto de lista. Terceiro, elementos aninhados foram perdidos.
ZygD 03/04/19
2

Minha maneira simples de resolver isso:

Crie um novo arquivo Python como: json_to_csv.py

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

Depois de adicionar este código, salve o arquivo e execute no terminal:

python json_to_csv.py input.txt output.csv

Espero que isso lhe ajude.

ATÉ MAIS!

Gabriel Pires
fonte
1
Esta amostra funciona como um encanto! obrigado por compartilhar i foi capaz de converter meu arquivo JSON em CSV usando este script python
Mostafa
2

Surpreendentemente, descobri que nenhuma das respostas postadas aqui até agora lida corretamente com todos os cenários possíveis (por exemplo, dict aninhados, listas aninhadas, nenhum valor etc.).

Esta solução deve funcionar em todos os cenários:

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

Tente isto

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

Esse código funciona para qualquer arquivo json

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

A resposta de Alec McGail modificada para dar suporte ao JSON com 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

Obrigado!

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

Se considerarmos o exemplo abaixo para converter o arquivo no formato json em arquivo no formato csv.

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

O código abaixo converterá o arquivo json (data3.json) em arquivo 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')])

O código acima mencionado foi executado no pycharm instalado localmente e converteu com êxito o arquivo json no arquivo csv. Espero que esta ajuda para converter os arquivos.

SABYASACHI SAHA
fonte
0

Como os dados parecem estar em um formato de dicionário, parece que você realmente deve usar csv.DictWriter () para realmente exibir as linhas com as informações de cabeçalho apropriadas. Isso deve permitir que a conversão seja tratada de alguma maneira mais fácil. O parâmetro fieldnames configuraria a ordem corretamente, enquanto a saída da primeira linha, como os cabeçalhos, permitiria que ela fosse lida e processada posteriormente por csv.DictReader ().

Por exemplo, Mike Repass usou

output = csv.writer(sys.stdout)

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

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

No entanto, basta alterar a configuração inicial para output = csv.DictWriter (conjunto de arquivos, nomes de campo = dados [0] .keys ())

Observe que, como a ordem dos elementos em um dicionário não está definida, pode ser necessário criar entradas de nomes de campo explicitamente. Depois de fazer isso, o escritor irá funcionar. As gravações funcionam como mostrado originalmente.

sabbahillel
fonte
0

Infelizmente, não tenho reputação de dar uma pequena contribuição à incrível resposta de @Alec McGail. Eu estava usando Python3 e precisei converter o mapa em uma lista após o comentário do @Alexis R.

Além disso, eu descobri que o gravador csv estava adicionando um CR extra ao arquivo (tenho uma linha vazia para cada linha com dados dentro do arquivo csv). A solução foi muito fácil, seguindo a resposta de @Jason R. Coombs para este segmento: CSV em Python adicionando um retorno de carro extra

Você precisa simplesmente adicionar o parâmetro lineterminator = '\ n' ao csv.writer. Será:csv_w = csv.writer( out_file, lineterminator='\n' )

derwyddon
fonte
0

Você pode usar esse código para converter um arquivo json em arquivo csv. Depois de ler o arquivo, estou convertendo o objeto em pandas dataframe e salvando-o em um arquivo 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
fonte
isso não leva em consideração subcampos (como "campos" no exemplo) - o subobjeto está em uma coluna em vez de seu conteúdo separado em colunas individuais também.
Cribber
0

Talvez eu esteja atrasado para a festa, mas acho que lidei com o mesmo problema. Eu tinha um arquivo json que era assim

Estrutura de arquivo JSON

Eu só queria extrair algumas chaves / valores desse arquivo json. Então, eu escrevi o código a seguir para extrair o mesmo.

    """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 isso ajude. Para detalhes sobre como esse código funciona, você pode conferir aqui

Udit Hari Vashisht
fonte
0

Esta é uma modificação da resposta de @ MikeRepass. Esta versão grava o CSV em um arquivo e funciona para o Python 2 e o 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
fonte