2009-12-09 57 views
97

我有一個JSON文件,我想轉換爲CSV文件。我如何用Python做到這一點?如何將JSON轉換爲CSV?

我想:

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

然而,它沒有工作。我使用Django和我收到的錯誤是:

file' object has no attribute 'writerow' 

所以,後來我試過如下:

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

然後我得到的錯誤:

sequence expected 

樣品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 
    } 
    } 
] 
+2

我們需要更多的細節。請從json文件發佈示例 – 2009-12-09 04:08:26

+0

您可以發佈json文件嗎?直到你做到,我們無法真正幫助你。 – 2009-12-09 05:58:01

+0

我有我的json文件示例。 謝謝 – 2009-12-09 06:24:00

回答

19

此代碼應該和rk給你,假設你的JSON數據在一個名爲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()) 
+1

嗯,沒有 - 'csv_file.writerow'(當然沒有'f.writerow',我假設你在那裏犯了一個錯字!)想要一個序列,而不是一個字典 - 在你的例子中,每個項目是一個字典。這將適用於OTHER特殊情況,正如我在我的答案中所標識的 - JSON文件中有一個數組數組;它不適用於一系列對象,這是你似乎試圖解決的特殊情況(需要一個'csv.DictWriter' - 當然你需要提取字段名稱並決定一個訂單爲了實例化它! - )。 – 2009-12-09 04:54:21

+0

糟糕,錯字。感謝您的支持。 – 2009-12-09 05:55:00

30

JSON可以代表各種各樣的數據結構 - 一個JS「對象」是大致像Python字典(具有字符串鍵),一個JS「陣列」​​大致像一個Python列表,並且可以嵌套只要最後的「葉」元素是數字或字符串。

CSV本質上可以僅代表一個2D表 - 可選地帶有第一行「標題」,即「列名」,它可以使表可解釋爲列表的字典,而不是正常的解釋,列表清單(再次,「葉子」元素可以是數字或字符串)。

因此,在一般情況下,您無法將任意JSON結構轉換爲CSV。在一些特殊情況下,您可以(不需要進一步嵌套的數組的數組;所有對象的數組都具有完全相同的鍵)。哪種特殊情況適用於您的問題?解決方案的細節取決於你有哪些特殊情況。考慮到你甚至沒有提到哪一個適用的令人驚訝的事實,我懷疑你可能沒有考慮過這個約束,實際上這兩個可用的情況都不適用,而且你的問題是不可能解決的。但請澄清!

76

我不確定這個問題是否已經解決,但讓我粘貼我所做的參考。

首先,您的JSON具有嵌套的對象,因此它通常不能直接轉換爲CSV。 你需要改變的東西是這樣的:

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

這裏是我的代碼來生成CSV:

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

你會得到輸出:

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

這是以前的工作,但很抱歉我可以得到的東西,沒有硬編碼 我的東西更好ID我可以使用 f.writerow(一) 和一個是一些variabel我 – 2009-12-09 08:16:57

+0

之前 感謝前申報我幾乎完美的工作。在導出的CSV中,某些字段被'[u''和'']'包圍。什麼是(非後處理)解決方法?如果有一個... :) – Dror 2014-07-10 12:20:43

+3

下面我已經展示了一種更通用的方法,無需對其進行硬編碼 – 2015-08-26 21:11:49

3

Dan's proposed solution有問題,但這對我有用:

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

凡「測試。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 } } 
] 
+0

在您的示例數據上嘗試您的程序時出現錯誤 C:\ curl> python json2csv。py 回溯(最近一次通話最後一次): 文件「json2csv.py」,第11行,在 f.writerow([item ['pk'],item ['model']] + item ['fields']] .values()) TypeError:只能連接列表(不是「dict_values」)到列表 – 2015-12-10 11:54:28

+0

剛剛在Python 2.7.9中再次嘗試它,它對我來說工作正常。 – Amanda 2015-12-10 19:33:59

24

一個通用的解決方案,它轉化平坦對象CSV的任何JSON列表

傳遞input.json文件作爲命令行上的第一個參數

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

一個重要的評論 - 這段代碼從第一行的字段推斷出列/標題。如果你的JSON數據有'鋸齒'列,即可以說row1有5列,但row2有6列,那麼你需要對數據進行第一遍以獲得所有列的總集合並將其用作標題。 – 2012-12-07 21:59:40

+0

由於我的數據是我需要的解決方案的很大一部分,因爲我的JSON沒有參差不齊,因爲我在一個現有的腳本中運行它,所以對輸出進行了一些微小的調整。 – MichaelF 2014-04-24 15:00:13

+1

此代碼還假定值將以與標題行中的鍵相同的順序輸出。雖然這可能是幸運的,但它絕不是保證。 – RyanHennig 2015-07-28 19:09:36

0

由於數據看起來是字典格式,因此看起來您應該使用csv.DictWriter()實際輸出具有適當標題信息的行,這應該允許轉換爲處理起來要容易一些然後,fieldnames參數將正確設置順序,而第一行的輸出作爲標題將允許它在稍後被csv.DictReader()讀取和處理。

例如,麥克再通過使用

output = csv.writer(sys.stdout) 

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

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

然而只是改變初始設置到 輸出= csv.DictWriter(filesetting,字段名=數據[0] .keys())

注意由於未定義字典中元素的順序,因此可能必須顯式創建字段名稱條目。一旦你這樣做,作家就會工作。寫入然後按原來的方式工作。

3

正如在前面的答案中所提到的,將json轉換爲csv的困難是因爲json文件可以包含嵌套字典,因此是一個多維數據結構與csv是一個二維數據結構。但是,將多維結構轉換爲csv的一種好方法是將多個csvs與主鍵綁定在一起。

在您的示例中,第一個csv輸出將列「pk」,「model」,「fields」作爲列。 「pk」和「model」的值很容易得到,但是因爲「fields」列包含一個字典,它應該是它自己的csv,並且因爲「codename」看起來是主鍵,所以可以用作輸入爲「字段」完成第一個csv。第二個csv包含「fields」列中的字典,其中codename作爲可用於將2個csvs綁定在一起的主鍵。

這裏是你的json文件的解決方案,它將嵌套字典轉換爲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") 
56

我假設你的JSON文件將解碼成字典列表。首先,我們需要一個功能,將壓平的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 

您的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 
} 

應用此功能後,輸入JSON對象數組中的每個字典:

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

,並找到相關的列名:

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

不難通過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)) 

我希望這有助於!

+2

它的作家,而不是write_row – philgo20 2016-09-02 19:51:11

+0

@ philgo20感謝您的發現,編輯 – 2016-09-02 20:10:49

+0

@AlecMcGail它不與pyhton3.x – EmptyData 2017-04-14 08:03:01

1

這個工作比較好。 它將json壓扁以將其寫入csv文件。 嵌套的元素進行管理:)

這對蟒蛇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) 

享受。

22

隨着pandaslibrary,這就像使用兩個命令一樣簡單!

pandas.read_json() 

要將JSON字符串轉換爲大熊貓對象(無論是串聯或數據幀)。然後,假設結果被存儲爲df

df.to_csv() 

哪些可以返回一個字符串或直接寫信給一個CSV文件。

根據以前答案的詳細程度,我們都應該感謝大熊貓的快捷方式。

0

修改亞歷克McGail的答案,以支持內部

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 

感謝與列表JSON!

8

這將是使用方便csv.DictWriter(),具體實現可以是這樣的:

def read_json(filename): 
    return json.loads(open(filename).read()) 
def write_csv(data,filename): 
    with open(filename) 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') 

注意,這裏假設你所有的JSON對象具有相同的字段。

這裏是reference它可以幫助你。

+0

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/評論/低質量帖/ 14462200) – purplepsycho 2016-12-01 10:04:30

+1

Thx爲您的建議。 – ReturnHttp402 2016-12-02 05:07:16

+0

@purplepsycho我用downvote找到了這個答案,這個答案只能用於鏈接。新用戶可能不知道這個鏈接並不是一個好的答案,但已經糾正了這個問題。我upvoted;也許你也可以鼓勵新用戶繼續參與我們的社區? – Mawg 2017-01-19 08:40:27

1

我簡單的方法來解決這個問題:

像創建一個新的Python文件:json_to_csv。PY

添加以下代碼:添加

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

此代碼後,保存文件並運行在終端:

python json_to_csv.py input.txt output.csv

我希望這可以幫助您。

SEEYA!

+0

這個樣本就像一個魅力!感謝分享我能夠使用這個python腳本將我的json文件轉換爲CSV – Mostafa 2017-10-23 16:52:19

2

我知道自從問這個問題已經有很長時間了,但我想我可以添加到其他人的答案中,並共享一篇博文,我想以一種非常簡潔的方式解釋解決方案。

這裏是link

打開文件進行寫入

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

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

確保關閉文件以節省內容

employ_data.close() 
0

它不是做一個非常聰明的方式,但我有同樣的問題,這個工作對我來說:

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