我如何将JSON转换为CSV?
我有一个JSON文件,我想隐藏到一个CSV文件。 我怎样才能用Python做到这一点?
我试过了:
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 } } ]
我不确定这个问题是否已经解决,但让我粘贴我所做的参考。
首先,你的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
我假设你的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 ) )
我希望这有帮助!
JSON可以表示各种各样的数据结构 – 一个JS“对象”就像Python字典(带有字符串键),一个类似于Python列表的JS“数组”,只要最终的“叶“元素是数字或字符串。
CSV可以基本上只代表一个二维表 – 可选地带有第一行“标题”,即“列名”,它可以使表可解释为列表的列表,而不是正常的解释,列表列表(同样,“叶”元素可以是数字或字符串)。
因此,在一般情况下,您不能将任意的JSON结构转换为CSV。 在一些特殊的情况下,你可以(没有进一步嵌套的数组数组;所有对象都有完全相同的键)。 哪个特殊情况适用于您的问题? 解决方案的细节取决于你有哪些特殊情况。 鉴于你甚至没有提到哪一个适用的令人震惊的事实,我怀疑你可能没有考虑到这个约束,实际上也没有可用的情况,你的问题是不可能解决的。 但请澄清!
将平面对象的任何json列表转换为csv的通用解决方案。
在命令行上传递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())
这个代码应该适合你,假设你的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())
有了pandas
图书馆 , 就像使用两个命令一样简单!
pandas.read_json()
将JSON字符串转换为熊猫对象(序列或数据框)。 然后,假设结果存储为df
:
df.to_csv()
它可以返回一个字符串或直接写入一个CSV文件。
根据以前答案的详细程度,我们都应该感谢大熊猫的捷径。
使用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对象都有相同的字段。
这里是可以帮助你的参考 。
正如在前面的答案中所提到的,将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")
我在丹的提议的解决方案遇到麻烦,但这对我工作:
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())
其中“test.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 } } ]
这工作比较好。 它将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)
请享用。
我简单的方法来解决这个问题:
创建一个新的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
我希望这可以帮助你。
再见!
我知道这个问题已经被问了很长时间了,但是我想我可以添加到其他人的答案中,并分享一篇博客文章,我想以一个非常简洁的方式来解释这个解决方案。
这是链接
打开一个文件写入
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()
由于数据看起来是字典格式,所以看起来应该使用csv.DictWriter()来实际输出具有适当标题信息的行。 这应该使转换处理更容易一些。 然后,fieldnames参数将正确地设置顺序,而第一行的输出作为标题将允许它被csv.DictReader()稍后读取和处理。
例如,Mike Repass使用
output = csv.writer(sys.stdout) output.writerow(data[0].keys()) # header row for row in data: output.writerow(row.values())
但是,只需将初始设置更改为output = csv.DictWriter(filesetting,fieldnames = data [0] .keys())
请注意,由于字典中元素的顺序未定义,因此您可能必须显式创建字段名称条目。 一旦你这样做,作家将工作。 然后写入工作原来显示。
修改了Alec McGail的答案来支持里面列表的JSON
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
谢谢!