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

如何保存以自定义对象为键的字典?json与pickle保存报错

自定义对象作为字典键的序列化问题

核心结论

  • JSON:必须将自定义对象转换为JSON支持的基础类型(str、int、float等)才能作为字典键,JSON规范不允许复杂对象作为键。
  • Pickle:支持自定义对象作为字典键,但需要你的类实现__hash__和__eq__方法,确保对象可哈希且能正确比较。

为什么JSON保存会报错?

从报错信息可以明确看到:TypeError: keys must be str, int, float, bool or None, not my_node,JSON编码器只允许基础类型作为字典键,自定义对象不在允许范围内。

JSON解决方案:转换键为基础类型

方案1:用对象的属性作为键

直接提取自定义对象的唯一标识属性(比如name)作为字典键:

import json
class my_node(object):
    def __init__(self, name):
        self.name=name
        
node=my_node(1)
# 使用对象的name属性作为字典键
my_dict={node.name: 1}
print(my_dict)

# 保存JSON
with open('test.json', "w") as outfile:
    json.dump(my_dict, outfile)

# 读取验证
with open('test.json', "r") as infile:
    loaded = json.load(infile)
print(loaded[node.name])  # 输出1

方案2:将对象序列化为字符串作为键

如果需要保留对象的完整信息,可以先把对象转成JSON字符串,再作为键:

import json
class my_node(object):
    def __init__(self, name):
        self.name=name
        
node=my_node(1)
# 将对象转为JSON字符串作为键
node_key = json.dumps({"name": node.name})
my_dict={node_key: 1}

# 保存JSON
with open('test.json', "w") as outfile:
    json.dump(my_dict, outfile)

# 读取并还原对象
with open('test.json', "r") as infile:
    loaded_dict = json.load(infile)
# 解析键还原对象
node_info = json.loads(next(iter(loaded_dict.keys())))
new_node = my_node(node_info["name"])
print(loaded_dict[node_key])  # 输出1

Pickle的处理方式

Pickle支持将自定义对象作为字典键,但要求类实现__hash__和__eq__方法——这是字典键的基本要求(可哈希、可比较),否则序列化后读取时无法正确匹配键。

Pickle示例代码

import pickle
class my_node(object):
    def __init__(self, name):
        self.name=name
    
    # 基于name属性实现哈希
    def __hash__(self):
        return hash(self.name)
    
    # 基于name属性实现相等判断
    def __eq__(self, other):
        if isinstance(other, my_node):
            return self.name == other.name
        return False
        
node=my_node(1)
my_dict={node: 1}
print(my_dict)

# 用Pickle保存
with open('test.pkl', "wb") as outfile:
    pickle.dump(my_dict, outfile)

# 读取验证
with open('test.pkl', "rb") as infile:
    loaded_dict = pickle.load(infile)
print(loaded_dict)  # 输出{<__main__.my_node object at 0x...>: 1}
# 用新创建的同属性对象获取值
new_node = my_node(1)
print(loaded_dict[new_node])  # 输出1

内容的提问来源于stack exchange,提问作者Mihai.Mehe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 13:05:18