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

如何序列化包含PlayerElo类实例的字典以实现JSON的保存与加载?

解决自定义PlayerElo对象的JSON序列化问题

遇到自定义对象没法直接JSON序列化的情况太常见了,核心问题就是JSON模块不知道怎么把你的PlayerElo对象转换成它能识别的基本数据类型。这里给你两种实用的解决方案,你可以根据自己的代码结构选:

方案一:自定义JSON编码器和解码器

这种方法不用改动你的PlayerElo类太多,只需要写一个编码器告诉JSON怎么处理你的对象,再写一个解码器把JSON转回来。

序列化(保存)代码

import json

class PlayerElo:
    """ 用于表示Elo评分系统中的玩家类 """
    def __init__(self, name: str, id: str, rating):
        self.id = id
        self.name = name
        self.eloratings = {0: 1500}
        self.elomatches = {0: 0}
        self.initialrating = rating

# 自定义编码器,处理PlayerElo对象
class PlayerEloEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, PlayerElo):
            # 把对象的所有属性打包成字典,加个类型标记方便后续识别
            return {
                '__type__': 'PlayerElo',
                'id': obj.id,
                'name': obj.name,
                'eloratings': obj.eloratings,
                'elomatches': obj.elomatches,
                'initialrating': obj.initialrating
            }
        # 其他类型交给默认逻辑处理
        return super().default(obj)

# 准备数据并保存到文件
playersElo = {
    1: PlayerElo("Alice", "player_1", 1500),
    2: PlayerElo("Bob", "player_2", 1500)
}

with open('players_elo.json', 'w', encoding='utf-8') as f:
    json.dump(playersElo, f, cls=PlayerEloEncoder, indent=4)

反序列化(加载)代码

def player_elo_decoder(obj):
    # 识别我们标记的类型,把字典转回PlayerElo对象
    if obj.get('__type__') == 'PlayerElo':
        player = PlayerElo(obj['name'], obj['id'], obj['initialrating'])
        player.eloratings = obj['eloratings']
        player.elomatches = obj['elomatches']
        return player
    return obj

# 从文件加载并转换
with open('players_elo.json', 'r', encoding='utf-8') as f:
    loaded_players = json.load(f, object_hook=player_elo_decoder)

# 验证一下
print(loaded_players[1].name)  # 输出Alice
print(loaded_players[2].eloratings)  # 输出{0: 1500}

方案二:给PlayerElo类添加序列化/反序列化方法

这种方法把序列化逻辑封装在类内部,更符合面向对象的设计,代码也更整洁。

import json

class PlayerElo:
    """ 用于表示Elo评分系统中的玩家类 """
    def __init__(self, name: str, id: str, rating):
        self.id = id
        self.name = name
        self.eloratings = {0: 1500}
        self.elomatches = {0: 0}
        self.initialrating = rating
    
    # 把对象转成可序列化的字典
    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'eloratings': self.eloratings,
            'elomatches': self.elomatches,
            'initialrating': self.initialrating
        }
    
    # 从字典创建对象的类方法
    @classmethod
    def from_dict(cls, data):
        player = cls(data['name'], data['id'], data['initialrating'])
        player.eloratings = data['eloratings']
        player.elomatches = data['elomatches']
        return player

# 保存数据
playersElo = {
    1: PlayerElo("Alice", "player_1", 1500),
    2: PlayerElo("Bob", "player_2", 1500)
}
# 先把每个PlayerElo转成字典
serializable_data = {k: v.to_dict() for k, v in playersElo.items()}
with open('players_elo.json', 'w', encoding='utf-8') as f:
    json.dump(serializable_data, f, indent=4)

# 加载数据
with open('players_elo.json', 'r', encoding='utf-8') as f:
    loaded_data = json.load(f)
# 把每个字典转回PlayerElo对象
loaded_players = {k: PlayerElo.from_dict(v) for k, v in loaded_data.items()}

# 验证
print(loaded_players[2].initialrating)  # 输出1500

小提示

  • 不管用哪种方法,都要确保PlayerElo的所有属性都是JSON可序列化的(比如你的eloratings和elomatches是字典,里面的键值都是int,没问题);如果以后加了其他自定义对象属性,也要同步处理它们的序列化。
  • indent=4是为了让生成的JSON文件更易读,实际部署可以去掉节省空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:44:41