在Python中将嵌套的 JSON 转换为 CSV
在本文中,我们将讨论如何在Python中将嵌套的 JSON 转换为 CSV。
一个简单的 JSON 文件示例:
正如您在示例中看到的,单个键值对由冒号 (:) 分隔,而每个键值对由逗号 (,) 分隔。这里,“姓名”、“个人资料”、“年龄”和“位置”是关键字段,对应的值分别是“ Amit Pathak ”、“软件工程师”、“24”、“英国伦敦”。
嵌套 JSON 是一种结构,其中一个或多个字段的值可以是另一种 JSON 格式。例如,按照我们将用来转换为 CSV 格式的以下示例。
嵌套 JSON 文件的示例:
在上面的示例中,关键字段“ article ”具有另一个 JSON 格式的值。如果需要,JSON 支持多个嵌套以创建复杂的 JSON 文件。
嵌套的 JSON 到 CSV 的转换
我们的工作是将 JSON 文件转换为 CSV 格式。我们需要执行这种转换的原因可能有很多。在电子表格 GUI 应用程序(如 Google Sheets 或 MS Excel)中打开时,CSV 很容易阅读。它们易于用于数据分析任务。在处理表格数据时,它也是一种广泛排除的格式,因为与 JSON 格式不同,它易于人类查看。
方法
- 第一步是将 JSON 文件作为Python dict 对象读取。这将有助于我们利用Python dict 方法来执行一些操作。 read_json()函数用于任务,它将文件路径和扩展名作为参数,并将 JSON 文件的内容作为Python dict 对象返回。
- 我们使用normalize_json()函数对 dict 对象进行规范化。它检查 dict 对象中的键值对。如果该值再次是 dict,则它将键字符串与嵌套字典的键字符串连接起来。
- 使用generate_csv_data()函数创建所需的 CSV 数据。此函数使用逗号 (,) 连接每个记录,然后所有这些单独的记录都附加一个新行( Python中的 '\n' )。
- 在最后一步中,我们将前面步骤中生成的 CSV 数据写入通过filepath参数提供的首选位置。
使用的文件: article.json 文件
{
"article_id": 3214507,
"article_link": "http://sample.link",
"published_on": "17-Sep-2020",
"source": "moneycontrol",
"article": {
"title": "IT stocks to see a jump this month",
"category": "finance",
"image": "http://sample.img",
"sentiment": "neutral"
}
}
示例:将 JSON 转换为 CSV
Python
import json
def read_json(filename: str) -> dict:
try:
with open(filename, "r") as f:
data = json.loads(f.read())
except:
raise Exception(f"Reading {filename} file encountered an error")
return data
def normalize_json(data: dict) -> dict:
new_data = dict()
for key, value in data.items():
if not isinstance(value, dict):
new_data[key] = value
else:
for k, v in value.items():
new_data[key + "_" + k] = v
return new_data
def generate_csv_data(data: dict) -> str:
# Defining CSV columns in a list to maintain
# the order
csv_columns = data.keys()
# Generate the first row of CSV
csv_data = ",".join(csv_columns) + "\n"
# Generate the single record present
new_row = list()
for col in csv_columns:
new_row.append(str(data[col]))
# Concatenate the record with the column information
# in CSV format
csv_data += ",".join(new_row) + "\n"
return csv_data
def write_to_file(data: str, filepath: str) -> bool:
try:
with open(filepath, "w+") as f:
f.write(data)
except:
raise Exception(f"Saving data to {filepath} encountered an error")
def main():
# Read the JSON file as python dictionary
data = read_json(filename="article.json")
# Normalize the nested python dict
new_data = normalize_json(data=data)
# Pretty print the new dict object
print("New dict:", new_data)
# Generate the desired CSV data
csv_data = generate_csv_data(data=new_data)
# Save the generated CSV data to a CSV file
write_to_file(data=csv_data, filepath="data.csv")
if __name__ == '__main__':
main()
Python
import json
import pandas
def read_json(filename: str) -> dict:
try:
with open(filename, "r") as f:
data = json.loads(f.read())
except:
raise Exception(f"Reading {filename} file encountered an error")
return data
def normalize_json(data: dict) -> dict:
new_data = dict()
for key, value in data.items():
if not isinstance(value, dict):
new_data[key] = value
else:
for k, v in value.items():
new_data[key + "_" + k] = v
return new_data
def main():
# Read the JSON file as python dictionary
data = read_json(filename="article.json")
# Normalize the nested python dict
new_data = normalize_json(data=data)
print("New dict:", new_data, "\n")
# Create a pandas dataframe
dataframe = pandas.DataFrame(new_data, index=[0])
# Write to a CSV file
dataframe.to_csv("article.csv")
if __name__ == '__main__':
main()
Python
import json
import pandas
def read_json(filename: str) -> dict:
try:
with open(filename, "r") as f:
data = json.loads(f.read())
except:
raise Exception(f"Reading {filename} file encountered an error")
return data
def create_dataframe(data: list) -> pandas.DataFrame:
# Declare an empty dataframe to append records
dataframe = pandas.DataFrame()
# Looping through each record
for d in data:
# Normalize the column levels
record = pandas.json_normalize(d)
# Append it to the dataframe
dataframe = dataframe.append(record, ignore_index=True)
return dataframe
def main():
# Read the JSON file as python dictionary
data = read_json(filename="details.json")
# Generate the dataframe for the array items in
# details key
dataframe = create_dataframe(data=data['details'])
# Renaming columns of the dataframe
print("Normalized Columns:", dataframe.columns.to_list())
dataframe.rename(columns={
"results.school": "school",
"results.high_school": "high_school",
"results.graduation": "graduation",
"education.graduation.major": "grad_major",
"education.graduation.minor": "grad_minor"
}, inplace=True)
print("Renamed Columns:", dataframe.columns.to_list())
# Convert dataframe to CSV
dataframe.to_csv("details.csv", index=False)
if __name__ == '__main__':
main()
输出:
同样可以通过使用 Pandas Python库来实现。 Pandas是一个免费的源Python库,用于数据操作和分析。它通过将数据转换为pandas.DataFrame格式来执行操作。它提供了许多可以在数据帧上执行的功能和操作。
方法
- 第一步是将 JSON 文件作为Python dict 对象读取。这将有助于我们利用Python dict 方法来执行一些操作。 read_json()函数用于任务,它将文件路径和扩展名作为参数,并将 JSON 文件的内容作为Python dict 对象返回。
- 我们使用normalize_json()函数对 dict 对象进行规范化。它检查 dict 对象中的键值对。如果该值再次是 dict,则它将键字符串与嵌套字典的键字符串连接起来。
- 在这一步中,我们使用pandas.DataFrame() ,而不是手动将单个对象附加为 CSV 的每个记录 方法。它接收 dict 对象并以 Pandas DataFrame 对象的形式生成所需的 CSV 数据。上面代码中值得注意的一件事是,“ new_data ” dict 变量的值存在于列表中。原因是在传递字典以创建 Pandas 数据帧时,dict 的值必须是一个值列表,其中每个值代表该键名或列名的每一行中存在的值。在这里,我们只有一行。
- 我们使用pandas.DataFrame.to_csv() 方法将路径和文件名保存为输入参数,并将步骤 3 中生成的 CSV 数据保存为 CSV。
示例:使用 Pandas 将 JSON 转换为 CSV
Python
import json
import pandas
def read_json(filename: str) -> dict:
try:
with open(filename, "r") as f:
data = json.loads(f.read())
except:
raise Exception(f"Reading {filename} file encountered an error")
return data
def normalize_json(data: dict) -> dict:
new_data = dict()
for key, value in data.items():
if not isinstance(value, dict):
new_data[key] = value
else:
for k, v in value.items():
new_data[key + "_" + k] = v
return new_data
def main():
# Read the JSON file as python dictionary
data = read_json(filename="article.json")
# Normalize the nested python dict
new_data = normalize_json(data=data)
print("New dict:", new_data, "\n")
# Create a pandas dataframe
dataframe = pandas.DataFrame(new_data, index=[0])
# Write to a CSV file
dataframe.to_csv("article.csv")
if __name__ == '__main__':
main()
输出:
当我们对 JSON 进行单层嵌套时,上面两个示例很好,但是随着嵌套的增加和记录的增加,上述代码需要更多的编辑。我们可以使用 pandas 库轻松处理此类 JSON。让我们看看如何。
将 N 嵌套 JSON 转换为 CSV
可以使用Pandas中的“ json_normalize() ”方法以最少的代码处理 JSON 中任意数量的嵌套和记录。
句法:
json_normalize(data)
正在使用的文件: details.json 文件
{
"details": [
{
"id": "STU001",
"name": "Amit Pathak",
"age": 24,
"results": {
"school": 85,
"high_school": 75,
"graduation": 70
},
"education": {
"graduation": {
"major": "Computers",
"minor": "Sociology"
}
}
},
{
"id": "STU002",
"name": "Yash Kotian",
"age": 32,
"results": {
"school": 80,
"high_school": 58,
"graduation": 49
},
"education": {
"graduation": {
"major": "Biology",
"minor": "Chemistry"
}
}
},
{
"id": "STU003",
"name": "Aanchal Singh",
"age": 28,
"results": {
"school": 90,
"high_school": 70,
"graduation":65
},
"education": {
"graduation": {
"major": "Art",
"minor": "IT"
}
}
},
{
"id": "STU004",
"name": "Juhi Vadia",
"age": 23,
"results": {
"school": 95,
"high_school": 89,
"graduation": 83
},
"education": {
"graduation": {
"major": "IT",
"minor": "Social"
}
}
}
]
}
这里的“ details ”键由一个包含 4 个元素的数组组成,其中每个元素包含3 级嵌套的 JSON对象。这些对象中的每一个中的“主要”和“次要”键都在第 3 级嵌套中。
方法
- 第一步是将 JSON 文件作为Python dict 对象读取。这将有助于我们利用Python dict 方法来执行一些操作。 read_json()函数用于任务,它将文件路径和扩展名作为参数,并将 JSON 文件的内容作为Python dict 对象返回。
- 我们已经对 details 数组中存在的每个 JSON 对象进行了迭代。在每次迭代中,我们首先对 JSON 进行规范化并创建一个临时数据帧。然后将此数据帧附加到输出数据帧。
- 完成后,列名被重命名以获得更好的可见性。如果我们看到控制台输出,“ major ”列在重命名之前被命名为“ education.graduation.major ”。这是因为“ json_normalize() ”方法使用完整嵌套中的键来生成列名以避免重复列问题。因此,在 JSON 嵌套中,“教育”是第一级,“毕业”是第二级,“专业”是第三级。因此,“ education.graduation.major ”列被简单地重命名为“graduation”。
- 重命名列后, to_csv()方法将 Pandas 数据框对象以 CSV 格式保存到提供的文件位置。
示例:将 n 嵌套 JSON 转换为 CSV
Python
import json
import pandas
def read_json(filename: str) -> dict:
try:
with open(filename, "r") as f:
data = json.loads(f.read())
except:
raise Exception(f"Reading {filename} file encountered an error")
return data
def create_dataframe(data: list) -> pandas.DataFrame:
# Declare an empty dataframe to append records
dataframe = pandas.DataFrame()
# Looping through each record
for d in data:
# Normalize the column levels
record = pandas.json_normalize(d)
# Append it to the dataframe
dataframe = dataframe.append(record, ignore_index=True)
return dataframe
def main():
# Read the JSON file as python dictionary
data = read_json(filename="details.json")
# Generate the dataframe for the array items in
# details key
dataframe = create_dataframe(data=data['details'])
# Renaming columns of the dataframe
print("Normalized Columns:", dataframe.columns.to_list())
dataframe.rename(columns={
"results.school": "school",
"results.high_school": "high_school",
"results.graduation": "graduation",
"education.graduation.major": "grad_major",
"education.graduation.minor": "grad_minor"
}, inplace=True)
print("Renamed Columns:", dataframe.columns.to_list())
# Convert dataframe to CSV
dataframe.to_csv("details.csv", index=False)
if __name__ == '__main__':
main()
输出:
$ Console Output
—–
Normalized Columns: [‘id’, ‘name’, ‘age’, ‘results.school’, ‘results.high_school’, ‘results.graduation’, ‘education.graduation.major’, ‘education.graduation.minor’]
Renamed Columns: [‘id’, ‘name’, ‘age’, ‘school’, ‘high_school’, ‘graduation’, ‘grad_major’, ‘grad_minor’]