You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含重复键的JSON文件处理与验证技术问题求助

处理JSON重复键并自动重命名的解决方案

核心思路

标准JSON库的json.load()会直接覆盖重复键且不报错,逐行用json.loads()又因JSON常跨多行导致误判。解决关键是保留所有键的原始出现顺序,不能依赖默认解析逻辑,得用能捕获所有键值对的工具或自定义钩子。

实用方案与代码示例

方案1:自定义解码器(轻量,适合小文件)

直接继承标准库的JSONDecoder,重写object_pairs_hook——这个钩子能拿到所有键值对的原始列表(包括重复项),在里面处理重命名逻辑:

import json

def handle_duplicate_keys(pairs, target_key="port"):
    result = {}
    key_count = {}
    for key, val in pairs:
        if key == target_key:
            # 给重复的port计数,重命名为port0、port1...
            cnt = key_count.get(key, 0)
            new_key = f"{key}{cnt}"
            result[new_key] = val
            key_count[key] += 1
        else:
            # 非目标键直接保留,若需处理所有重复键,去掉此判断即可
            result[key] = val
    return result

# 自定义解码器类
class DuplicateKeyFixer(json.JSONDecoder):
    def __init__(self, target_key="port", **kwargs):
        super().__init__(object_pairs_hook=lambda pairs: handle_duplicate_keys(pairs, target_key), **kwargs)

# 使用示例
with open("your_json_file.json", "r", encoding="utf-8") as f:
    fixed_data = json.load(f, cls=DuplicateKeyFixer)
print(fixed_data)

方案2:用ijson流式解析(适合大文件)

如果JSON文件体积过大,加载到内存会占用过多资源,就用ijson逐token解析,既能精准捕获每个键的出现,还能定位重复键的具体位置:

先安装依赖:pip install ijson

import ijson

def process_large_json(file_path, target_key="port"):
    final_data = {}
    current_obj = None
    current_key = None
    key_counter = {target_key: 0}
    parent_stack = []

    with open(file_path, "rb") as f:
        for prefix, event, value in ijson.parse(f):
            if event == "start_map":
                # 进入新对象,记录上下文
                new_obj = {}
                if not parent_stack:
                    current_obj = final_data
                else:
                    parent_obj = parent_stack[-1]
                    parent_obj[current_key] = new_obj
                parent_stack.append(new_obj)
            elif event == "end_map":
                # 退出当前对象
                parent_stack.pop()
                current_obj = parent_stack[-1] if parent_stack else None
            elif event == "map_key":
                # 处理键,重复的target_key重命名
                current_key = value
                if value == target_key:
                    current_key = f"{target_key}{key_counter[target_key]}"
                    key_counter[target_key] += 1
            elif event in ("string", "number", "boolean", "null") and current_obj is not None:
                # 给当前对象赋值
                current_obj[current_key] = value
    return final_data

# 使用示例
fixed_large_data = process_large_json("big_json_file.json")
print(fixed_large_data)

额外提示

  • 若需处理所有重复键(不止port),去掉代码中target_key的判断逻辑,改为对所有键统一计数即可。
  • 逐行验证误判的问题:JSON对象通常跨多行,逐行解析自然会报错,应按完整JSON对象解析,上述流式方案可定位到包含重复键的具体对象。

内容的提问来源于stack exchange,提问作者CandleWax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:55:22