skip to Main Content

I’m struggling cause I don’t know how to consume this JSON because in the "weather" part of the JSON it receives [0] as key-value and I don’t know how to declare it

{
  "coord": {
    "lon": -35.7353,
    "lat": -9.6658
  },
  "weather": [
    {
      "id": 801,
      "main": "Clouds",
      "description": "few clouds",
      "icon": "02d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 302.84,
    "feels_like": 305.59,
    "temp_min": 302.84,
    "temp_max": 302.84,
    "pressure": 1011,
    "humidity": 61
  },
  "visibility": 10000,
  "wind": {
    "speed": 7.2,
    "deg": 90
  },
  "clouds": {
    "all": 20
  },
  "dt": 1672689129,
  "sys": {
    "type": 1,
    "id": 8413,
    "country": "BR",
    "sunrise": 1672646788,
    "sunset": 1672692412
  },
  "timezone": -10800,
  "id": 3395981,
  "name": "MaceiĆ³",
  "cod": 200
}

my attempt looked like this, and it kept failing cause of the weather part. i’ve tried some stuff like UUID() but none of it seens to work (maybe i’m applying it the wrong way)

import Foundation

struct Response: Codable {
    
    var coord: Coord
    var weather: [Weather]?
    var main: Main
    var visibility: Int
    var wind: Wind
    var rain: Rain?
    var clouds: Clouds?
    var dt: Int
    var sys: Sys
    var timezone: Int
    var id: Int
    var name: String
    var cod: Int

}

struct Coord: Codable {
    var lon: Double
    var lat: Double
}

struct WeatherBase: Codable {
    var id: String { _id }
    private var _id: String
    var base: String
    
}

struct Weather: Codable {
    var id: Int
    var main: String
    var description: String
    var icon: String
}

struct Main: Codable {
    var temp: Double
    var feels_like: Double
    var temp_min: Double
    var temp_max: Double
    var pressure: Int
    var humidity: Int
}

struct Wind: Codable {
    var speed: Double
    var deg: Int
}

struct Rain: Codable{
    var umh: Int
}

struct Clouds: Codable {
    var all: Int
}

struct Sys: Codable {
    var type: Int
    var id: Int
    var country: String
    var sunrise: Int
    var sunset: Int
    
}

2

Answers


  1. I couldn’t reproduce your error using your code and json object. I just remove the WeatherBase struct because it was not used in any part.
    I open a playground to understand better you problem and add the following code.

    guard let filePath = Bundle.main.url(forResource: "filename", withExtension: "json") else { fatalError()}
    let data = try Data(contentsOf: filePath)
    let jsonDecoder = JSONDecoder()
    jsonDecoder.keyDecodingStrategy = .useDefaultKeys
    let jsonData = try? jsonDecoder.decode(Response.self, from: data)
    
    print(token?.weather![0].description)
    

    Result

    Optional("few clouds")
    

    I hope I`ve helped you.

    Login or Signup to reply.
  2. As I mentioned in my answer to your previous question,
    you need to check the docs to determine which fields are optional
    and amend your code accordingly. Note the extra var base: String property in the Response struct.

    The following SwiftUi code shows how to access the data
    that is retrieved from the openweathermap server, in particular the weather info.
    Use something similar for your UIKit code.

    Note that you must check the index before you access the data, as shown, otherwise your app will crash.

    struct ContentView: View {
        @State var result: Response?
        
        var body: some View {
            VStack {
                // the base property
                Text(result?.base ?? "no base").foregroundColor(.blue)
                // check index first
                if let kount = result?.weather?.count, kount > 0 {
                    Text(result?.weather![0].description ?? "no data")
                    Text(result?.weather![0].main ?? "no data")
                    Text(result?.weather![0].icon ?? "no data")
                } else {
                    Text("no data for weather[0]").foregroundColor(.red)
                }
                // or
                if let kount = result?.weather?.count, kount > 1 {
                    Text(result?.weather![1].description ?? "no data")
                    Text(result?.weather![1].main ?? "no data")
                    Text(result?.weather![1].icon ?? "no data")
                } else {
                    Text("no data for weather[1]").foregroundColor(.red)
                }
            }
             .onAppear {
                 downloadJSON { error in
                     if error == nil {
                         print("success")
                         // checks
                         if let theResult = result, let kount = theResult.weather?.count, kount > 0 {
                             print("---> base: (theResult.base)")
                             print("---> description: (theResult.weather![0].description)")
                             print("---> main: (theResult.weather![0].main)")
                             print("---> icon: (theResult.weather![0].icon)")
                         }
                        // alternative checks
                        if let theResult = result, let firstWeather = theResult.weather?.first {
                            print("---> base: (theResult.base)")
                            print("---> description: (firstWeather.description)")
                            print("---> main: (firstWeather.main)")
                            print("---> icon: (firstWeather.icon)")
                        }
                     } else {
                         print("error: (error)")
                     }
                 }
             }
        }
        
        func downloadJSON(completed: @escaping (Error?) -> ()){
            let token = "YOUR-TOKEN"
            if let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?appid=(token)&q=Maceio") {
                URLSession.shared.dataTask(with: url) { data, response, error in
                    if error == nil, let data = data {
                        do {
                            self.result = try JSONDecoder().decode(Response.self, from: data)
                            completed(nil)
                        }
                        catch {
                            completed(error)
                        }
                    }
                }.resume()
            }
        }
    }
    
    struct Response: Codable, Identifiable {  // <-- here
        var base: String // <-- here
        var coord: Coord
        var weather: [Weather]? // <-- here
        var main: Main?
        var visibility: Int?
        var wind: Wind?
        var rain: Rain?
        var clouds: Clouds?
        var dt: Int?
        var sys: Sys?
        var timezone: Int?
        var id: Int?
        var name: String?
        var cod: Int?
    }
    
    struct Coord: Codable {
        var lon: Double?
        var lat: Double?
    }
        
    struct Weather: Codable, Identifiable {  // <-- here
        var id: Int
        var main: String
        var description: String
        var icon: String
    }
    
    struct Main: Codable {
        var temp: Double?
        var feels_like: Double?
        var temp_min: Double?
        var temp_max: Double?
        var pressure: Int?
        var humidity: Int?
    }
    
    struct Wind: Codable {
        var speed: Double?
        var deg: Int?
    }
    
    struct Rain: Codable{
        var umh: Int?
    }
    
    struct Clouds: Codable {
        var all: Int?
    }
    
    struct Sys: Codable {
        var type: Int?
        var id: Int?
        var country: String?
        var sunrise: Int?
        var sunset: Int?
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search