Python脚本无法正确分隔JSON文件中的对象问题求助
解决Pokédex JSON数据追加异常问题
问题场景
开发Python版Pokédex作业时,遇到两个核心问题:
- 从
full_pokedex.json提取宝可梦数据追加到空的pokedex.json后,文件出现多个独立字典,无法形成合法的单一JSON结构。 - 尝试将源JSON改为数组格式后,触发
AttributeError: 'list' object has no attribute 'keys'错误。
用户代码
# importing modules import json from os import path # check if output file exists and load it filename = 'full_pokedex.json' if path.isfile(filename) is False: raise Exception("File not found") with open("full_pokedex.json", "r") as read_file: input_file_dict = json.load(read_file) # input field (for testing purposes) pkmn = input("Enter the name of a G1 starter Pokémon: ") # write Bulbasaur in json file if pkmn == "Bulbasaur": inc_id_list = [1] output_dict = dict() for id in input_file_dict.keys(): if int(id) in inc_id_list: output_dict[id] = input_file_dict.get(id) with open('pokedex.json', 'a') as output_json_file: json.dump(output_dict, output_json_file, indent = 1, separators=(',',": "), ensure_ascii=False) print("Data added to Pokédex") # write Charmender in json file if pkmn == "Charmander": inc_id_list = [4] output_dict = dict() for id in input_file_dict.keys(): if int(id) in inc_id_list: output_dict[id] = input_file_dict.get(id) with open('pokedex.json', 'a') as output_json_file: json.dump(output_dict, output_json_file, indent = 1, separators=(',',": "), ensure_ascii=False) print("Data added to Pokédex") # write Squirtle in json file if pkmn == "Squirtle": inc_id_list = [7] output_dict = dict() for id in input_file_dict.keys(): if int(id) in inc_id_list: output_dict[id] = input_file_dict.get(id) with open('pokedex.json', 'a') as output_json_file: json.dump(output_dict, output_json_file, indent = 1, separators=(',',": "), ensure_ascii=False) print("Data added to Pokédex")
源JSON(full_pokedex.json)
{ "1": { "id": 1, "name": "Bulbasaur", "type": "Plant", "HP": 45, "Attack": 49, "Defense": 49, "Sp. Attack": 65, "Sp. Defense": 65, "Speed": 45 }, "4": { "id": 4, "name": "Charmander", "type": "Fire", "HP": 39, "Attack": 52, "Defense": 43, "Sp. Attack": 60, "Sp. Defense": 50, "Speed": 65 }, "7": { "id": 7, "name": "Squirtle", "type": "Water", "HP": 44, "Attack": 48, "Defense": 65, "Sp. Attack": 50, "Sp. Defense": 64, "Speed": 43 } }
错误的追加结果(pokedex.json)
{ "1": { "id": 1, "name": "Bulbasaur", "type": "Plant", "HP": 45, "Attack": 49, "Defense": 49, "Sp. Attack": 65, "Sp. Defense": 65, "Speed": 45 } }{ "4": { "id": 4, "name": "Charmander", "type": "Fire", "HP": 39, "Attack": 52, "Defense": 43, "Sp. Attack": 60, "Sp. Defense": 50, "Speed": 65 } }{ "7": { "id": 7, "name": "Squirtle", "type": "Water", "HP": 44, "Attack": 48, "Defense": 65, "Sp. Attack": 50, "Sp. Defense": 64, "Speed": 43 } }
数组格式触发的错误栈
Traceback (most recent call last): File "c:\Users\crost\Documents\Projets\Pokemon\src\pokedex\pokedex.py", line 38, in <module> for id in input_file_dict.keys(): ^^^^^^^^^^^^^^^^^^^^ AttributeError: 'list' object has no attribute 'keys'
错误原因
- 直接追加JSON对象:使用
open('pokedex.json', 'a')模式写入时,每次json.dump()都会生成一个完整的JSON字典,多次追加后文件是多个JSON对象的拼接,不符合JSON语法规范。 - 数组格式适配错误:将源JSON改为数组后,
json.load()返回的是列表而非字典,代码中调用keys()方法自然报错,因为列表没有该属性。
解决方案
核心逻辑:先读取目标文件的现有数据,将新数据合并到现有字典中,再整体写入目标文件,保证JSON结构合法。同时优化重复代码,减少冗余。
修改后的代码
import json from os import path # 读取源宝可梦数据 source_file = 'full_pokedex.json' if not path.isfile(source_file): raise Exception("源文件不存在") with open(source_file, "r") as f: full_pokedex = json.load(f) # 定义宝可梦名字到ID的映射,避免重复if判断 pkmn_id_map = { "Bulbasaur": 1, "Charmander": 4, "Squirtle": 7 } # 获取用户输入 pkmn_name = input("Enter the name of a G1 starter Pokémon: ").strip() # 验证输入有效性 if pkmn_name not in pkmn_id_map: print("无效的宝可梦名字,请输入Bulbasaur、Charmander或Squirtle") exit() # 读取目标文件现有数据,不存在则初始化为空字典 target_file = 'pokedex.json' if path.isfile(target_file): with open(target_file, "r") as f: existing_pokedex = json.load(f) else: existing_pokedex = {} # 获取要添加的宝可梦ID并转换为字符串(匹配源数据的键格式) pkmn_id_str = str(pkmn_id_map[pkmn_name]) # 合并数据到现有字典 existing_pokedex[pkmn_id_str] = full_pokedex[pkmn_id_str] # 整体写入目标文件,覆盖原有内容 with open(target_file, "w", encoding="utf-8") as f: json.dump(existing_pokedex, f, indent=1, separators=(',', ": "), ensure_ascii=False) print(f"{pkmn_name}数据已添加到Pokédex")
关键修改说明
- 合并数据而非追加:先读取
pokedex.json的现有内容(如果存在),将新宝可梦数据合并到现有字典,再用w模式写入,确保文件是单一合法的JSON结构。 - 优化输入判断:用字典映射名字和ID,避免重复的if分支,代码更简洁。
- 格式兼容:将ID转换为字符串,匹配源JSON中键的格式(字符串类型的"1"、"4"等)。
正确的JSON结果
多次添加后,pokedex.json会是一个完整的字典:
{ "1": { "id": 1, "name": "Bulbasaur", "type": "Plant", "HP": 45, "Attack": 49, "Defense": 49, "Sp. Attack": 65, "Sp. Defense": 65, "Speed": 45 }, "4": { "id": 4, "name": "Charmander", "type": "Fire", "HP": 39, "Attack": 52, "Defense": 43, "Sp. Attack": 60, "Sp. Defense": 50, "Speed": 65 } }
内容的提问来源于stack exchange,提问作者Alexandre Vidal
相关产品推荐
相关产品推荐

