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

如何基于键名自定义Python字典值的JSON序列化编码规则?

问题解答

自定义编码器不生效的原因

json.JSONEncoder.default() 方法仅会处理JSON标准不支持、编码器无法原生序列化的类型。list属于JSON原生支持的类型,序列化时不会触发你重写的default方法,这是代码不生效的核心原因。

解决方案

方案1:按指定键名自定义缩进(无需标记类,适配频繁读写修改的需求)

该方案的规则直接写在序列化逻辑中,不需要在数据中添加任何额外标记,解析修改后重新保存也不会丢失规则,完全匹配需求。实现思路为:

  1. 预处理字典,将匹配指定键名的值单独序列化为无缩进字符串,用唯一占位符替换
  2. 对预处理后的字典做整体带缩进序列化
  3. 替换占位符为提前序列化好的无缩进内容,得到最终结果

代码示例:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 03:45:08