我刚刚开始学习Python,我的任务是将JSON转换为CSV文件,以分号作为定界符并具有三个约束。 我的JSON是:
{"_id": "5cfffc2dd866fc32fcfe9fcc",
"tuple5": ["system1/folder", "system3/folder"],
"tuple4": ["system1/folder/text3.txt", "system2/folder/text3.txt"],
"tuple3": ["system2/folder/text2.txt"],
"tuple2": ["system2/folder"],
"tuple1": ["system1/folder/text1.txt", "system2/folder/text1.txt"],
"tupleSize": 3}
输出CSV的格式应为:
system1 ; system2 ; system3
system1/folder ; ~ ; system3/folder
system1/folder/text3.txt ; system2/folder/text3.txt ; ~
~ ; system2/folder/text2.txt ; ~
~ ; system2/folder ; ~
system1/folder/text1.txt ; system2/folder/text1.txt ; ~
因此,三个约束条件是tupleSize
将指示行数,数组元素的第一部分,即sys1
,sys2
和sys3
将是数组元素,最后只有属于特定系统的那些元素才会在CSV文件中具有值(其余为~
)。
我发现了一些有关Python转换的帖子,例如this和this。它们都没有与这些相关的任何限制,我无法弄清楚该如何处理。
有人可以帮忙吗?
编辑:我应该提到数组元素是动态的,因此CSV文件中的行标题可能会有所不同。
答案 0 :(得分:0)
您想要做的是相当实质的,因此,如果这只是Python学习练习,我建议您从更多基本任务开始。
我还认为您已经将大多数人所说的行和列颠倒了,因此请注意,下面的所有内容(包括代码)都以与您在问题中使用它们的方式相反的方式使用它们。
无论如何,下面的代码首先会对数据进行预处理,以确定CSV文件的列或字段名称,并确保按'tupleSize'
键所指定的列数或字段数正确。 / p>
假定满足约束条件,然后第二次遍历数据,并从每个键值中提取列/字段值,将它们放入字典中,该字典的内容代表要写入输出文件的行,然后完成后会做到这一点。
已更新
已修改,以删除JSON对象字典中所有以“ _id”开头的键。
import csv
import json
import re
SEP = '/' # Value sub-component separator.
id_regex = re.compile(r"_id\d*")
json_string = '''
{"_id1": "5cfffc2dd866fc32fcfe9fc1",
"_id2": "5cfffc2dd866fc32fcfe9fc2",
"_id3": "5cfffc2dd866fc32fcfe9fc3",
"tuple5": ["system1/folder", "system3/folder"],
"tuple4": ["system1/folder/text3.txt", "system2/folder/text3.txt"],
"tuple3": ["system2/folder/text2.txt"],
"tuple2": ["system2/folder"],
"tuple1": ["system1/folder/text1.txt", "system2/folder/text1.txt"],
"tupleSize": 3}
'''
data = json.loads(json_string) # Convert JSON string into a dictionary.
# Remove non-path items from dictionary.
tupleSize = data.pop('tupleSize')
_ids = {key: data.pop(key)
for key in tuple(data.keys()) if id_regex.search(key)}
#print(f'_ids: {_ids}')
max_columns = int(tupleSize) # Use to check a contraint.
# Determine how many columns are present and what they are.
columns = set()
for key in data:
paths = data[key]
if not paths:
raise RuntimeError('key with no paths')
for path in paths:
comps = path.split(SEP)
if len(comps) < 2:
raise RuntimeError('component with no subcomponents')
columns.add(comps[0])
if len(columns) > max_columns:
raise RuntimeError('too many columns - conversion aborted')
# Create CSV file.
with open('converted_json.csv', 'w', newline='') as file:
writer = csv.DictWriter(file, delimiter=';', restval='~',
fieldnames=sorted(columns))
writer.writeheader()
for key in data:
row = {}
for path in data[key]:
column, *_ = path.split(SEP, maxsplit=1)
row[column] = path
writer.writerow(row)
print('Conversion complete')