📜  在Python中将嵌套的 JSON 转换为 CSV

📅  最后修改于: 2022-05-13 01:54:36.665000             🧑  作者: Mango

在Python中将嵌套的 JSON 转换为 CSV

在本文中,我们将讨论如何在Python中将嵌套的 JSON 转换为 CSV。

一个简单的 JSON 文件示例:

一个简单的 JSON 表示

正如您在示例中看到的,单个键值对由冒号 (:) 分隔,而每个键值对由逗号 (,) 分隔。这里,“姓名”、“个人资料”、“年龄”和“位置”是关键字段,对应的值分别是“ Amit Pathak ”、“软件工程师”、“24”、“英国伦敦”。

嵌套 JSON 是一种结构,其中一个或多个字段的值可以是另一种 JSON 格式。例如,按照我们将用来转换为 CSV 格式的以下示例。

嵌套 JSON 文件的示例:

嵌套的 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()


输出:

代码块 1 的Python控制台输出

代码块 1 的 CSV 输出

同样可以通过使用 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()

输出:

代码块 2 的Python控制台输出

代码块 2 的 CSV 输出

当我们对 JSON 进行单层嵌套时,上面两个示例很好,但是随着嵌套的增加和记录的增加,上述代码需要更多的编辑。我们可以使用 pandas 库轻松处理此类 JSON。让我们看看如何。

将 N 嵌套 JSON 转换为 CSV

可以使用Pandas中的“ json_normalize() ”方法以最少的代码处理 JSON 中任意数量的嵌套和记录。

句法:

正在使用的文件: 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()

输出:

代码块 3 的 CSV 输出