如何基于键名自定义Python字典值的JSON序列化编码规则?
问题解答
自定义编码器不生效的原因
json.JSONEncoder.default() 方法仅会处理JSON标准不支持、编码器无法原生序列化的类型。list属于JSON原生支持的类型,序列化时不会触发你重写的default方法,这是代码不生效的核心原因。
解决方案
方案1:按指定键名自定义缩进(无需标记类,适配频繁读写修改的需求)
该方案的规则直接写在序列化逻辑中,不需要在数据中添加任何额外标记,解析修改后重新保存也不会丢失规则,完全匹配需求。实现思路为:
- 预处理字典,将匹配指定键名的值单独序列化为无缩进字符串,用唯一占位符替换
- 对预处理后的字典做整体带缩进序列化
- 替换占位符为提前序列化好的无缩进内容,得到最终结果
代码示例:
import json import numpy as np def custom_json_dump(obj, no_indent_keys=None, indent=4, ensure_ascii=False, **kwargs): no_indent_keys = no_indent_keys or [] placeholder_prefix = "__NO_INDENT_PLACEHOLDER_" placeholder_suffix = "__" placeholders = {} counter = 0 def preprocess(data): nonlocal counter if isinstance(data, dict): processed_dict = {} for key, value in data.items(): if key in no_indent_keys: # 对指定键的值做无缩进序列化 serialized_val = json.dumps(value, ensure_ascii=ensure_ascii, indent=None) placeholder = f"{placeholder_prefix}{counter}{placeholder_suffix}" placeholders[placeholder] = serialized_val counter += 1 processed_dict[key] = placeholder else: processed_dict[key] = preprocess(value) return processed_dict elif isinstance(data, np.ndarray): # ndarray默认转列表,需要转字符串的话替换为 return str(data.tolist()) return data.tolist() else: return data processed_obj = preprocess(obj) # 整体序列化 raw_output = json.dumps(processed_obj, indent=indent, ensure_ascii=ensure_ascii, **kwargs) # 替换占位符为真实无缩进内容 for ph, content in placeholders.items(): raw_output = raw_output.replace(f'"{ph}"', content) return raw_output # 调用示例 mydict = { "mylist1": ["a", "b", "c"], "mylist2": ["a", "b", "c"], "mylist3": ["a", "b", "c"], "my_np_arr": np.array([1,2,3]) } output = custom_json_dump(mydict, no_indent_keys=["mylist1"]) print(output)
运行后输出和要求的预期效果完全一致。
方案2:所有列表/ndarray无缩进或转字符串
如果不需要按键名判断,要统一处理所有列表和ndarray,只需要修改上述preprocess函数的逻辑即可:
- 要所有列表无缩进:遇到
list类型就执行和指定键值相同的占位符替换逻辑 - 要所有列表/ndarray转字符串:遇到
list或np.ndarray类型直接返回str(value)即可
内容的提问来源于stack exchange,提问作者mluerig
相关产品推荐
相关产品推荐

