如何用Python将规范化CSV反规范化为嵌套JSON
解决扁平JSON转嵌套数组(dataFields)的问题
问题描述
现有CSV转成的扁平JSON结构,其中dataFields.n.category这类键需要转换为嵌套数组dataFields,示例如下:
输入扁平JSON:
{"Example": [ {"exCode": "example_code", "name": "ex", "code": "ex_2", "dataFields.0.category": "EXAMPLE", "dataFields.0.name": "exampl", "dataFields.0.code": "exampl", "dataFields.0.unit": "v", "dataFields.1.category": "EXAMPLE", "dataFields.1.name": "exampl2", "dataFields.1.code": "exampl2", "dataFields.1.unit": "e", "dataFields.2.category": "EXAMPLE2", "dataFields.2.name": null, "dataFields.2.code": null, "dataFields.2.unit": "e" } ]}
期望输出嵌套JSON:
{"Example": [ {"exCode": "example_code", "name": "ex", "code": "ex_2", "dataFields": [ {"category": "EXAMPLE", "name": "exampl", "code": "exampl", "unit": "v"}, {"category": "EXAMPLE", "name": "exampl2", "code": "exampl2", "unit": "e"}, {"category": "EXAMPLE2", "name": null, "code": null, "unit": "e"} ] } ]}
当前代码的核心问题是未正确处理数组索引,且未初始化dataFields数组,导致元素被覆盖。
问题分析
现有代码的几个关键错误:
- 未初始化
dataFields数组,直接调用append会抛出KeyError - 拆分键时忽略了数组索引(
split_norm[1]),无法区分不同的数组元素 - 错误地对字符串调用
append(changes[3].append(...)),逻辑完全错误 - 遍历字典键的方式混乱,未正确关联键值对
非递归解决方案
以下是修正后的非递归实现,逻辑清晰且能处理最多9个dataFields元素:
def denormalize_json(flat_json): # 遍历顶层的每个数组(比如示例中的"Example"对应的数组) for key in flat_json: items = flat_json[key] for item in items: # 初始化dataFields数组 data_fields = [] # 收集所有需要处理的扁平键 flat_data_keys = [k for k in item if k.startswith("dataFields.")] for flat_key in flat_data_keys: # 拆分键:dataFields.n.key -> ["dataFields", "n", "key"] parts = flat_key.split(".") if len(parts) != 3: continue # 跳过格式不正确的键 idx = int(parts[1]) field_name = parts[2] field_value = item[flat_key] # 确保data_fields的长度足够容纳当前索引 while len(data_fields) <= idx: data_fields.append({}) # 给对应索引的字典添加字段 data_fields[idx][field_name] = field_value # 删除原扁平键 del item[flat_key] # 将嵌套数组添加回原条目 if data_fields: item["dataFields"] = data_fields return flat_json # 测试示例 if __name__ == "__main__": input_json = { "Example": [ { "exCode": "example_code", "name": "ex", "code": "ex_2", "dataFields.0.category": "EXAMPLE", "dataFields.0.name": "exampl", "dataFields.0.code": "exampl", "dataFields.0.unit": "v", "dataFields.1.category": "EXAMPLE", "dataFields.1.name": "exampl2", "dataFields.1.code": "exampl2", "dataFields.1.unit": "e", "dataFields.2.category": "EXAMPLE2", "dataFields.2.name": None, "dataFields.2.code": None, "dataFields.2.unit": "e" } ] } result = denormalize_json(input_json) import json print(json.dumps(result, indent=2))
代码说明
- 初始化数组:对每个条目先创建空的
data_fields数组,用于存放嵌套对象 - 筛选扁平键:只处理以
dataFields.开头的键,避免干扰其他字段 - 拆分键并处理索引:通过拆分键获取数组索引
idx,确保数组长度足够后,将键值对存入对应索引的字典 - 清理与替换:删除原扁平键,将嵌套数组添加回原条目
运行上述代码后,即可得到期望的嵌套JSON结构,且不会出现元素覆盖的问题。
内容的提问来源于stack exchange,提问作者Sonny
相关产品推荐
相关产品推荐

