使用Python实现不同结构JSON文件间的数据转换迁移
Python 城市JSON结构转换实现方案
无需第三方依赖,直接使用Python标准库json即可完成转换,实现时用字典做行政区索引避免重复遍历数组,运行效率更高。
核心逻辑说明
- 读取源城市JSON数据时,以
admin_name为key建立索引映射,避免每次新增条目都全量遍历locations数组匹配 - 首次遇到某
admin_name时,按照目标结构补全所有默认字段初始化条目 - 后续遇到同
admin_name的城市数据,直接追加到对应条目的child数组中 - 读写文件全程使用
utf-8编码,避免特殊字符(如罗马尼亚语带变音符号的字符)乱码
完整实现代码
import json # 配置文件路径,可根据实际情况修改 SOURCE_JSON_PATH = "cities.json" TARGET_JSON_PATH = "locations_output.json" # 新行政区条目的默认结构 DEFAULT_LOCATION = { "slug": "", "description": "Judet", "meta": [ {"image_id": 45}, {"_icon": ""} ], "order": 0, "child": [] } def convert_city_data(): # 读取源城市数据 with open(SOURCE_JSON_PATH, "r", encoding="utf-8") as f: city_list = json.load(f) # 用字典做索引,key为admin_name,value为对应的location条目 location_index = {} # 行政区全局order计数器,从0开始递增 location_order_counter = 0 for city in city_list: admin_name = city.get("admin_name", "").strip() city_name = city.get("city", "").strip() if not admin_name or not city_name: # 跳过字段缺失的无效数据 continue if admin_name not in location_index: # 新建行政区条目 new_location = DEFAULT_LOCATION.copy() new_location["name"] = admin_name new_location["order"] = location_order_counter location_order_counter += 1 location_index[admin_name] = new_location # 往child数组追加城市条目 # 注:如果需要child的order按顺序递增,把下面的0替换为 len(location_index[admin_name]["child"]) + 1 即可 child_item = { "name": city_name, "order": 0 } location_index[admin_name]["child"].append(child_item) # 组装目标结构 target_data = { "locations": list(location_index.values()) } # 写入目标JSON文件,ensure_ascii=False保证非ASCII字符正常存储 with open(TARGET_JSON_PATH, "w", encoding="utf-8") as f: json.dump(target_data, f, ensure_ascii=False, indent=2) if __name__ == "__main__": convert_city_data()
使用说明
- 将代码里的
SOURCE_JSON_PATH替换为源城市JSON文件的实际路径,TARGET_JSON_PATH替换为要输出的目标文件路径后直接运行即可 - 代码默认跳过
admin_name或city字段为空的无效数据,可根据实际需求调整过滤规则 - 如果需要child节点的order按1、2、3顺序自动递增,按照代码注释修改对应order赋值即可
- 输出的JSON默认带2空格缩进方便阅读,不需要的话可以把
json.dump里的indent=2参数去掉
注:代码中对默认结构做了浅拷贝处理,由于默认值里的
meta字段是固定值不需要动态修改,浅拷贝足够使用;如果后续需要给不同行政区设置不同的meta内容,把DEFAULT_LOCATION.copy()替换为copy.deepcopy(DEFAULT_LOCATION)即可,记得在顶部导入copy模块。
内容的提问来源于stack exchange,提问作者Alexis
相关产品推荐
相关产品推荐

