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

Python脚本无法正确分隔JSON文件中的对象问题求助

解决Pokédex JSON数据追加异常问题

问题场景

开发Python版Pokédex作业时,遇到两个核心问题:

  1. 从full_pokedex.json提取宝可梦数据追加到空的pokedex.json后,文件出现多个独立字典,无法形成合法的单一JSON结构。
  2. 尝试将源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'

错误原因

  1. 直接追加JSON对象:使用open('pokedex.json', 'a')模式写入时,每次json.dump()都会生成一个完整的JSON字典,多次追加后文件是多个JSON对象的拼接,不符合JSON语法规范。
  2. 数组格式适配错误:将源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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 14:23:09