Python 中处理 JSON 重复键并合并值的完整教程

1次阅读

Python 中处理 JSON 重复键并合并值的完整教程

本文介绍如何在 python 中解析含重复键的 jsON 字符串,将相同键对应的所有值用分号连接为单一字符串,生成标准字典结构。核心方法是利用 json.loads 的 Object_pairs_hook 参数配合 itertools.groupby 实现键值聚合。

本文介绍如何在 python 中解析含重复键的 json 字符串,将相同键对应的所有值用分号连接为单一字符串,生成标准字典结构。核心方法是利用 `json.loads` 的 `object_pairs_hook` 参数配合 `itertools.groupby` 实现键值聚合。

在标准 JSON 规范中,对象(object)不允许存在重复键;但实际开发中(尤其在 API 响应、日志数据或遗留系统导出文件中),常会遇到人为构造或解析异常导致的重复键 JSON。Python 默认的 json.loads() 仅保留最后一个同名键的值,直接丢失其余数据。若需保留全部值并按指定分隔符合并,必须绕过默认行为,接管键值对的解析过程。

关键在于使用 json.loads() 的 object_pairs_hook 参数——它允许传入一个函数,接收原始 JSON 解析出的有序键值对列表(list of tuples),而非默认的 dict。这为我们提供了对重复键进行分组与聚合的机会。

以下是一个健壮、可复用的解决方案:

from itertools import groupby import json  def merge_duplicates(pairs):     """     将键值对列表按 key 分组,对每个 key 的所有 value 用 ';' 连接     注意:groupby 要求输入已按 key 排序     """     sorted_pairs = sorted(pairs, key=Lambda x: x[0])     for key, group in groupby(sorted_pairs, key=lambda x: x[0]):         values = [value for _, value in group]         yield key, ';'.join(values)  def parse_json_with_merged_keys(json_str):     """     解析含重复键的 JSON 字符串,自动合并同 key 的 value(以 ';' 分隔)     """     return json.loads(json_str, object_pairs_hook=lambda pairs: dict(merge_duplicates(pairs)))  # 示例使用 input_json = ''' {   "1061": "GROCERY",   "1073": "GM-HBC",   "4220": "PRODUCE",   "958": "MEAT",   "958": "DAIRY",   "958": "FROZEN" } '''  result = parse_json_with_merged_keys(input_json) print(result) # 输出: {'1061': 'GROCERY', '1073': 'GM-HBC', '4220': 'PRODUCE', '958': 'DAIRY;FROZEN;MEAT'}

工作原理说明:

立即学习Python免费学习笔记(深入)”;

  • json.loads(…, object_pairs_hook=…) 确保原始键值对顺序被完整传递(不被 dict 自动去重);
  • sorted(pairs, key=lambda x: x[0]) 按键升序排序,满足 groupby 的分组前提;
  • groupby(…, key=lambda x: x[0]) 将相同键的元组归为一组;
  • ‘;’.join(…) 高效拼接所有对应值,支持任意数量重复键。

⚠️ 注意事项:

  • 该方法不修改原始 JSON 字符串,仅影响解析逻辑;
  • 若原始 JSON 中 value 本身含分号(;),需提前转义或改用其他分隔符(如 ‘|’ 或 ‘n’),并在业务层做好兼容;
  • object_pairs_hook 在 Python 3.7+ 中稳定支持,无需额外依赖;
  • 对于超大 JSON 文件,建议结合 json.JSONDecoder 流式解析以控制内存占用。

? 进阶提示:
如需支持自定义分隔符或空值过滤,可扩展 merge_duplicates 函数:

def merge_duplicates(pairs, separator=';', skip_none=True):     sorted_pairs = sorted(pairs, key=lambda x: x[0])     for key, group in groupby(sorted_pairs, key=lambda x: x[0]):         values = [v for _, v in group if not (skip_none and v is None)]         yield key, separator.join(values)

通过此方案,你能在保持代码简洁的同时,精准解决“重复键值合并”这一典型数据清洗需求,适用于 etl、API 数据标准化及配置文件预处理等场景。

text=ZqhQzanResources