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

调用PokeApi获取宝可梦名称遇CodingKeys错误,结构体存疑求解决

解决PokeApi数据解析错误:No value associated with key CodingKeys(stringValue: "index"...)

错误信息

"No value associated with key CodingKeys(stringValue: "index", intValue: nil) ("index").", underlyingError: nil

问题代码

import UIKit

class ListViewController: UIViewController {
    @IBOutlet weak var pokemon1: UILabel!
    @IBOutlet weak var pokemon2: UILabel!
    @IBOutlet weak var pokemon3: UILabel!
    @IBOutlet weak var pokemon4: UILabel!
    @IBOutlet weak var pokemon5: UILabel!
    
    let url = "https://pokeapi.co/api/v2/pokemon"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData(from: url)
    }
    
    func fetchData(from url: String) {
        let url = URL(string: url)
        let defaultSession = URLSession(configuration: .default)
        let dataTask = defaultSession.dataTask(with: url!) { (data: Data?, response: URLResponse?, error: Error?) in
            if(error != nil) {
                print(String(describing: error))
                return
            }
            
            var json: Pokemon
            
            do {
                json = try JSONDecoder().decode(Pokemon.self, from: data!)
                Swift.print(json)
                
//                DispatchQueue.main.async {
//                    self.pokemon1.text = json.name
//                    self.pokemon3.text = json[2].name
//                    self.pokemon4.text = json[3].name
//                    self.pokemon5.text = json[4].name
//                    //callback: fonction que j'appelle à la suite d'un évènement
//                }
            } catch {
                print(error)
                return
            }
        }
        dataTask.resume() // Commence la dataTask si elle n'est pas en marche actuellement
    }
    
    struct Pokemon: Codable {
        let results: Results
    }
    
    struct Results: Codable {
        let name: String
        let index: String
    }
}

API返回数据

{
  "count": 1154,
  "next": "https://pokeapi.co/api/v2/pokemon?offset=20&limit=20",
  "previous": null,
  "results": [
    {
      "name": "bulbasaur",
      "url": "https://pokeapi.co/api/v2/pokemon/1/"
    },
    {
      "name": "ivysaur",
      "url": "https://pokeapi.co/api/v2/pokemon/2/"
    },
    {
      "name": "venusaur",
      "url": "https://pokeapi.co/api/v2/pokemon/3/"
    },
    {
      "name": "charmander",
      "url": "https://pokeapi.co/api/v2/pokemon/4/"
    },
    {
      "name": "charmeleon",
      "url": "https://pokeapi.co/api/v2/pokemon/5/"
    },
    {
      "name": "charizard",
      "url": "https://pokeapi.co/api/v2/pokemon/6/"
    },
    {
      "name": "squirtle",
      "url": "https://pokeapi.co/api/v2/pokemon/7/"
    },
    {
      "name": "wartortle",
      "url": "https://pokeapi.co/api/v2/pokemon/8/"
    },
    {
      "name": "blastoise",
      "url": "https://pokeapi.co/api/v2/pokemon/9/"
    },
    {
      "name": "caterpie",
      "url": "https://pokeapi.co/api/v2/pokemon/10/"
    },
    {
      "name": "metapod",
      "url": "https://pokeapi.co/api/v2/pokemon/11/"
    },
    {
      "name": "butterfree",
      "url": "https://pokeapi.co/api/v2/pokemon/12/"
    },
    {
      "name": "weedle",
      "url": "https://pokeapi.co/api/v2/pokemon/13/"
    },
    {
      "name": "kakuna",
      "url": "https://pokeapi.co/api/v2/pokemon/14/"
    },
    {
      "name": "beedrill",
      "url": "https://pokeapi.co/api/v2/pokemon/15/"
    },
    {
      "name": "pidgey",
      "url": "https://pokeapi.co/api/v2/pokemon/16/"
    },
    {
      "name": "pidgeotto",
      "url": "https://pokeapi.co/api/v2/pokemon/17/"
    },
    {
      "name": "pidgeot",
      "url": "https://pokeapi.co/api/v2/pokemon/18/"
    },
    {
      "name": "rattata",
      "url": "https://pokeapi.co/api/v2/pokemon/19/"
    },
    {
      "name": "raticate",
      "url": "https://pokeapi.co/api/v2/pokemon/20/"
    }
  ]
}

问题分析与修正方案

错误根源在于Codable结构体定义和API返回数据不匹配:

  • 错误1:API中results是数组([]包裹),但代码里定义为单个Results对象,类型不匹配
  • 错误2:API返回的结果里没有index字段,只有name和url,错误定义的index导致解析失败

修正后的代码

import UIKit

class ListViewController: UIViewController {
    @IBOutlet weak var pokemon1: UILabel!
    @IBOutlet weak var pokemon2: UILabel!
    @IBOutlet weak var pokemon3: UILabel!
    @IBOutlet weak var pokemon4: UILabel!
    @IBOutlet weak var pokemon5: UILabel!
    
    let url = "https://pokeapi.co/api/v2/pokemon"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData(from: url)
    }
    
    func fetchData(from url: String) {
        guard let url = URL(string: url) else {
            print("无效的URL")
            return
        }
        
        let defaultSession = URLSession(configuration: .default)
        let dataTask = defaultSession.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            
            if let error = error {
                print("请求错误:\(error)")
                return
            }
            
            guard let data = data else {
                print("未获取到数据")
                return
            }
            
            do {
                let pokemonResponse = try JSONDecoder().decode(PokemonResponse.self, from: data)
                print(pokemonResponse)
                
                DispatchQueue.main.async {
                    // 避免数组越界
                    if pokemonResponse.results.count >= 1 {
                        self.pokemon1.text = pokemonResponse.results[0].name
                    }
                    if pokemonResponse.results.count >= 2 {
                        self.pokemon2.text = pokemonResponse.results[1].name
                    }
                    if pokemonResponse.results.count >= 3 {
                        self.pokemon3.text = pokemonResponse.results[2].name
                    }
                    if pokemonResponse.results.count >= 4 {
                        self.pokemon4.text = pokemonResponse.results[3].name
                    }
                    if pokemonResponse.results.count >= 5 {
                        self.pokemon5.text = pokemonResponse.results[4].name
                    }
                }
            } catch {
                print("解析错误:\(error)")
                return
            }
        }
        dataTask.resume()
    }
    
    struct PokemonResponse: Codable {
        let count: Int
        let next: String?
        let previous: String?
        let results: [PokemonResult]
    }
    
    struct PokemonResult: Codable {
        let name: String
        let url: String
    }
}

关键修改点

  1. 重命名结构体为PokemonResponse,明确对应API的完整响应,添加API返回的count、next、previous字段(可按需删除)
  2. 将results字段类型改为[PokemonResult],匹配API的数组结构
  3. 将Results重命名为PokemonResult,并把index替换为API存在的url字段
  4. 增加空值判断和数组越界防护,避免崩溃
  5. 使用[weak self]防止循环引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:15:42