Search code examples
iosswiftxcodealamofiredecoder

Error in decoding: The data couldn't be read. Alamofire


I was trying to parse JSON through JSONDecoder and using Alamofire to fetch the data. However, when I run the app, it shows that the data couldn't be read because of the incorrect format. I have tried many things but still did not work. Any help would be appreciated. Sources are below:

VC:

class SecondTaskVC: UIViewController {

var weatherModel = [WeatherModelDecodable]()

override func viewDidLoad() {
    let url = URL(string: "https://api.openweathermap.org/data/2.5/forecast?lat=42.874722&lon=74.612222&APPID=079587841f01c6b277a82c1c7788a6c3")

    Alamofire.request(url!).responseJSON { (response) in

        let result = response.data

        do{
            let decoder = JSONDecoder()
            self.weatherModel = try decoder.decode([WeatherModelDecodable].self, from: result!) // it shows this line as a problem

            for weather in self.weatherModel {
                print(weather.city.name)
            }
        }catch let error{
            print("error in decoding",error.localizedDescription)

        }

    }
     }
   }

Data Model:

struct WeatherModelDecodable: Decodable {
  let city: CityDecodable
}

struct CityDecodable: Decodable {
  let name: String
 }

Solution

  • Actually the response structure is different from what you are trying to do at this line,

    self.weatherModel = try decoder.decode([WeatherModelDecodable].self, from: result!)
    

    The response is not an array as you can see it in a json viewer by hitting this Url in any browser. You are expecting an array of json objects but its not. So if you decode it as a single object, it will decode properly as below,

    let weatherModel = try decoder.decode(WeatherModelDecodable.self, from: result!)
    print(weatherModel.city.name)
    

    So, SecondTaskVC will look like this,

    class SecondTaskVC: UIViewController {
    
        var weatherModel: WeatherModelDecodable?
    
        override func viewDidLoad() {
            let url = URL(string: "https://api.openweathermap.org/data/2.5/forecast?lat=42.874722&lon=74.612222&APPID=079587841f01c6b277a82c1c7788a6c3")
    
            Alamofire.request(url!).responseJSON { (response) in
    
                let result = response.data
    
                do{
                    let decoder = JSONDecoder()
                    self.weatherModel = try decoder.decode(WeatherModelDecodable.self, from: result!)
                    print(self.weatherModel!.city.name)
                }catch let error{
                    print("error in decoding",error.localizedDescription)
    
                }
    
              }
            }
     }
    

    You should decode the respective objects with the same structure you are getting in the response.

    enter image description here