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
相关产品推荐
相关产品推荐

