Home > Enterprise >  Swift problems parsing JSON
Swift problems parsing JSON

Time:02-18

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)

  • Related