I would like to make a mini app with pokeapi which contains the pokemon.
I'm having a lot of problems parsing this particular JSON, the data doesn't come out in the TableView.
This is website: https://pokeapi.co/docs/v2#info
In the press console: typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
Below is my code:
DataManager.swift
import UIKit
protocol DataManagerDelegate {
func didUpdateStruct(_ dataManager: DataManager, dataModel: [DataModel])
func didFailWithError(error: Error)
}
struct DataManager {
let baseURL = "https://pokeapi.co/api/v2/pokemon"
var delegate: DataManagerDelegate?
func fetchUrl() {
let urlString = "\(baseURL)"
performRequest(with: urlString)
}
func performRequest(with urlString: String) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
if let pokemons = self.parseJSON(safeData) {
self.delegate?.didUpdateStruct(self, dataModel: pokemons)
}
}
}
task.resume()
}
}
func parseJSON(_ dataModel: Data) -> [DataModel]? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode([DataModel].self, from: dataModel)
return decodedData
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
DataModel.swift
import UIKit
struct DataModel: Codable {
let results: [Results]
}
struct Results: Codable {
let name: String?
}
CodePudding user response:
The error is pretty clear. codingPath: []
tells you that the parsing failed at the root object. You are trying to decode an array [DataModel]
when you should decode only DataModel
:
let decodedData = try decoder.decode(DataModel.self, from: dataModel)
I would also advise to name your data model better, e.g.:
struct PokemonList: Codable {
let results: [Pokemon]
}
struct Pokemon: Codable {
let name: String?
}
Then it should be obvious that you want to parse a PokemonList
and return just the array of pokemons:
func parseJSON(_ data: Data) -> [Pokemon]? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(PokemonList.self, from: data)
return decodedData.results
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
CodePudding user response:
The response you get is a dictionary as the root object whereas you are decoding it using an array. Please replace
let decodedData = try decoder.decode([DataModel].self, from: dataModel)
with
let decodedData = try decoder.decode(DataModel.self, from: dataModel)