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

自定义JSON编码器未被json.dump调用的问题排查

问题原因与解决方案

为什么json.dump()没触发自定义编码器?

json.dumps()直接调用编码器的encode()方法,但json.dump()默认使用iterencode()的非一次性模式,不会触发你重写的encode()逻辑——这就是两种方法表现不一致的核心原因。

另外你原始代码还有个隐患:在encode()里直接修改了原始字典self.G的键,会导致后续使用该对象时,元组键已经被替换成字符串,产生意外副作用。


解决方案1:修复自定义编码器(支持嵌套结构+无副作用)

重写iterencode()方法强制触发自定义逻辑,同时递归处理所有层级的字典,且不修改原始对象:

from collections.abc import MutableMapping
import json
import numpy as np

class JSONSerializer(json.JSONEncoder):
    def encode(self, obj):
        # 递归转换所有字典的元组键,生成新对象不修改原始数据
        def transform(o):
            if isinstance(o, MutableMapping):
                new_dict = {}
                for key, value in o.items():
                    if isinstance(key, tuple):
                        str_key = f"{key[0]}:{key[1]}"
                        new_dict[str_key] = transform(value)
                    else:
                        new_dict[key] = transform(value)
                return new_dict
            elif isinstance(o, (list, tuple)):
                return [transform(item) for item in o]
            else:
                # 额外处理numpy浮点数,避免json序列化失败
                return float(o) if isinstance(o, np.float64) else o

        transformed_obj = transform(obj)
        return super().encode(transformed_obj)

    def iterencode(self, o, _one_shot=False):
        # 让dump时的iterencode调用自定义的encode方法
        yield self.encode(o)

class Agent(object):
    def __init__(self, states, alpha=0.15, random_factor=0.2):
        self.state_history = [((0, 0), 0)] # state, reward
        self.alpha = alpha
        self.random_factor = random_factor
        
        self.G = {}
        self.init_reward(states)

    def init_reward(self, states):
        for i, row in enumerate(states):
            for j, col in enumerate(row):
                self.G[(j,i)] = np.random.uniform(high=1.0, low=0.1)
    
    def memorize(self):
        with open("memory.json", "w") as w:
            json.dump(self.G, w, cls=JSONSerializer)

if __name__ == "__main__":
    robot = Agent(states=np.zeros((6, 6)), alpha=0.1, random_factor=0.25)
    print(robot.G)
    robot.memorize()

解决方案2:直接转换字典(更简洁)

如果只有顶层字典的键是元组,不需要自定义编码器,直接生成转换后的字典再序列化:

# 修改Agent类的memorize方法即可
def memorize(self):
    # 把元组键转成字符串,同时转换numpy浮点数为原生浮点数
    converted_G = {f"{k[0]}:{k[1]}": float(v) for k, v in self.G.items()}
    with open("memory.json", "w") as w:
        json.dump(converted_G, w)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:05:53