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

Python中如何将含自定义类对象列表的变量保存至JSON文件并读取

解决方法

JSON默认只能序列化数字、字符串、列表、字典等基础类型,无法直接识别自定义类对象,你可以选择以下两种方案解决:

方案一:转成JSON支持的格式存储(生成可读的JSON存档)

步骤1:给自定义类添加序列化方法

在你的Card、Player、Human、AI类中新增to_dict()方法,将类的所有需要存档的属性转换为字典,同时添加类型标记方便加载时还原:

# 示例(根据你自己类的属性调整字段即可)
class Card:
    def __init__(self, name, attack, health):
        self.name = name
        self.attack = attack
        self.health = health
    # 新增序列化方法
    def to_dict(self):
        return {
            "type": "Card", # 类型标记
            "name": self.name,
            "attack": self.attack,
            "health": self.health
        }

class Player:
    def __init__(self, name, cards):
        self.name = name
        self.cards = cards
    def to_dict(self):
        return {
            "type": self.__class__.__name__, # 自动获取子类类型Human/AI
            "name": self.name,
            # 嵌套的Card对象也要逐一转字典
            "cards": [card.to_dict() for card in self.cards]
        }

class Human(Player):
    # 继承父类的to_dict即可,有额外属性再补充
    pass

class AI(Player):
    pass

步骤2:修改保存逻辑

将所有自定义类对象列表转成字典列表后再序列化:

def save_file():
    save_name = input("Save name (You will use this to load) > ")
    path = f'path_to_dir{save_name}.json'
    data = {
        'total_players' : total_players,
        'players' : [p.to_dict() for p in players],
        'dead_players' : [p.to_dict() for p in dead_players],
        'num_of_humans' : num_of_humans,
        'num_of_ai' : num_of_ai,
        'total_cards' : total_cards,
        'cards' : [c.to_dict() for c in cards]
    }
    with open(path, 'w+', encoding='utf-8') as f:
        # 加indent和ensure_ascii参数生成格式化、支持中文的JSON
        json.dump(data, f, indent=2, ensure_ascii=False)

步骤3:编写反序列化方法+修改加载逻辑

先写一个辅助函数将字典还原为对应的类对象,同时注意加载时要声明global修改全局变量,还要修正你原来写错的key和多余的str()转换:

# 辅助函数:字典转自定义类对象
def dict_to_obj(data_dict):
    obj_type = data_dict.get("type")
    if obj_type == "Card":
        return Card(
            name = data_dict["name"],
            attack = data_dict["attack"],
            health = data_dict["health"]
        )
    elif obj_type == "Human" or obj_type == "AI":
        # 先还原玩家持有的卡牌对象
        card_list = [dict_to_obj(c) for c in data_dict["cards"]]
        if obj_type == "Human":
            return Human(name=data_dict["name"], cards=card_list)
        else:
            return AI(name=data_dict["name"], cards=card_list)
    # 非自定义类型直接返回原值
    return data_dict

def load_file():
    # 声明要修改全局变量,否则赋值的是函数内部的局部变量
    global total_players, players, dead_players, num_of_humans, num_of_ai, total_cards, cards
    load_name = input("Enter the name of your save > ")
    path_two = f'path_to_dir{load_name}.json'
    with open(path_two, 'r', encoding='utf-8') as f: 
        sf = json.load(f) 
        total_players = sf['total_players']
        players = [dict_to_obj(p) for p in sf['players']]
        dead_players = [dict_to_obj(p) for p in sf['dead_players']]
        num_of_humans = sf['num_of_humans']
        num_of_ai = sf['num_of_ai']
        total_cards = sf['total_cards'] # 修正原来写错的key
        cards = [dict_to_obj(c) for c in sf['cards']]

方案二:用pickle直接序列化(更简单,不需要修改类)

如果你不需要存档文件是可读的JSON格式,用Python自带的pickle模块可以直接序列化自定义类对象,代码改动极小:

import pickle

def save_file():
    save_name = input("Save name (You will use this to load) > ")
    path = f'path_to_dir{save_name}.pkl'
    data = {
        'total_players' : total_players,
        'players' : players,
        'dead_players' : dead_players,
        'num_of_humans' : num_of_humans,
        'num_of_ai' : num_of_ai,
        'total_cards' : total_cards,
        'cards' : cards
    }
    # 注意用二进制写模式wb
    with open(path, 'wb') as f:
        pickle.dump(data, f)

def load_file():
    global total_players, players, dead_players, num_of_humans, num_of_ai, total_cards, cards
    load_name = input("Enter the name of your save > ")
    path_two = f'path_to_dir{load_name}.pkl'
    # 注意用二进制读模式rb
    with open(path_two, 'rb') as f: 
        sf = pickle.load(f) 
        total_players = sf['total_players']
        players = sf['players']
        dead_players = sf['dead_players']
        num_of_humans = sf['num_of_humans']
        num_of_ai = sf['num_of_ai']
        total_cards = sf['total_cards']
        cards = sf['cards']

注意:pickle生成的是二进制文件,不要加载来源不明的pkl文件,存在安全风险,自己个人项目使用完全没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:24:03