如何用Python无需硬编码将嵌套字典存储为CSV?
问题描述
我有如下嵌套字典/对象,要求层级字段的列名以父键作为前缀(例如"properties"下的"displayOnlyNewOrChangedRecords"对应列名properties_displayOnlyNewOrChangedRecords,"query"下的字段对应query_fields、query_filter、query_sortBy_fieldId等列)。请问如何在无需硬编码数据的前提下,使用Python将该嵌套字典存储为CSV文件?
示例字典:
{ "description": "", "id": "1", "name": "List All", "properties": { "displayOnlyNewOrChangedRecords": false }, "query": { "fields": [], "filter": "", "formulaFields": [], "groupBy": [], "sortBy": [ { "fieldId": 6, "order": "DESC" } ], "tableId": "bsjuwuqzy" }, "type": "table", "usedCount": 2, "usedLast": "2022-08-09T16:32:00Z" }
解决方案
核心思路是先递归扁平化嵌套字典,自动生成带父键前缀的字段名,再将扁平化后的字典写入CSV文件,全程无需硬编码任何字段。
1. 编写扁平化函数
这个函数会递归处理嵌套的字典和列表,自动为每个字段拼接父键前缀;对于列表元素,会添加索引后缀(避免多个元素字段名冲突),同时保留空列表的字段:
def flatten_dict(d, parent_key='', sep='_'): items = [] for k, v in d.items(): # 拼接父键与当前键,生成新字段名 new_key = f"{parent_key}{sep}{k}" if parent_key else k if isinstance(v, dict): # 递归处理嵌套字典 items.extend(flatten_dict(v, new_key, sep=sep).items()) elif isinstance(v, list): if not v: # 空列表直接保留字段 items.append((new_key, v)) else: # 遍历列表元素,处理嵌套字典或直接记录值 for i, item in enumerate(v): if isinstance(item, dict): items.extend(flatten_dict(item, f"{new_key}{sep}{i}", sep=sep).items()) else: items.append((f"{new_key}{sep}{i}", item)) else: # 普通值直接记录 items.append((new_key, v)) return dict(items)
2. 处理字典并写入CSV
使用上述函数扁平化示例字典,再通过Python内置的csv模块写入文件:
import csv # 示例嵌套字典 sample_dict = { "description": "", "id": "1", "name": "List All", "properties": { "displayOnlyNewOrChangedRecords": False }, "query": { "fields": [], "filter": "", "formulaFields": [], "groupBy": [], "sortBy": [ { "fieldId": 6, "order": "DESC" } ], "tableId": "bsjuwuqzy" }, "type": "table", "usedCount": 2, "usedLast": "2022-08-09T16:32:00Z" } # 扁平化字典 flattened_data = flatten_dict(sample_dict) # 写入CSV文件 with open('output.csv', 'w', newline='', encoding='utf-8') as csv_file: # 用扁平化后的键作为CSV列名 writer = csv.DictWriter(csv_file, fieldnames=flattened_data.keys()) writer.writeheader() writer.writerow(flattened_data)
输出效果示例
生成的CSV文件列名会包含:description, id, name, properties_displayOnlyNewOrChangedRecords, query_fields, query_filter, query_formulaFields, query_groupBy, query_sortBy_0_fieldId, query_sortBy_0_order, query_tableId, type, usedCount, usedLast
如果需要调整前缀分隔符(比如用.代替_),只需修改flatten_dict函数的sep参数即可。
内容的提问来源于stack exchange,提问作者Eliot Kim

