Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Decoding JSON data in Swift

I’m trying to decode some JSON data, and I ran into a problem with CodingKeys. I’m able to decode the whole JSON without a problem until I add an enum with coding keys.

The working code looks like this

import Foundation

// Top-level response struct
struct WeatherData: Codable {
    let weather: [Weather]
    let main: MainWeather
    let visibility: Double
    let wind: Wind
    let clouds: Clouds
    let sys: System
    let name: String
}

// Weather condition struct (array)
struct Weather: Codable {
    let id: Int
    let main: String
    let description: String
}

// Main weather data struct
struct MainWeather: Codable {
    let temp: Double
    let pressure: Int
    let humidity: Double

}

// Wind data struct
struct Wind: Codable {
    let speed: Double
    let deg: Int
}

struct Clouds: Codable {
    let all: Double
}

// System data struct
struct System: Codable {
    let sunrise: TimeInterval
    let sunset: TimeInterval
}

It stops decoding when I change the code to this

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import Foundation

// Top-level response struct
struct WeatherData: Codable {
    let weather: [Weather]
    let main: MainWeather
    let visibility: Double
    let wind: Wind
    let clouds: Clouds
    let sys: System
    let name: String
}

// Weather condition struct (array)
struct Weather: Codable {
    let id: Int
    let main: String
    let description: String
}

// Main weather data struct
struct MainWeather: Codable {
    let temp: Double
    let pressure: Int
    let humidity: Double
    let tempMin: Double
    let tempMax: Double
    let feelsLike: Double
    let seaLevel: Double
    let grndLevel: Double
    
    
    //     Custom coding keys to map JSON keys with underscores
    enum CodingKeys: String, CodingKey {
        case temp
        case feelsLike = "feels_like"
        case tempMin = "temp_min"
        case tempMax = "temp_max"
        case pressure
        case humidity
        case seaLevel  = "sea_level"
        case grndLevel = "grnd_level"
    }
}

// Wind data struct
struct Wind: Codable {
    let speed: Double
    let deg: Int
}

struct Clouds: Codable {
    let all: Double
}

// System data struct
struct System: Codable {
    let sunrise: TimeInterval
    let sunset: TimeInterval
}


My code for decoding looks like this

private let baseURL = URL(string: "https://api.openweathermap.org/data/2.5/weather")!
    
    func fetchWeather(for location: String) async throws -> WeatherData {
        
        var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false)!
                components.queryItems = [
                    URLQueryItem(name: "q", value: location.lowercased()),
                    URLQueryItem(name: "appid", value: Constants.apiKey),
                    URLQueryItem(name: "units", value: "metric")
                ]
        
        guard let fetchURL = components.url else {
                    throw FetchError.invalidURL
                }
        
        let (data, response) = try await URLSession.shared.data(from: fetchURL)
        
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
            throw FetchError.badResponse
        }
        
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let weather = try decoder.decode(WeatherData.self, from: data)
        
        return weather
    }

And finally, the JSON data looks like this

{
"coord": {
"lon": 13.3776,
"lat": 49.7475
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 283.88,
"feels_like": 283.38,
"temp_min": 282.31,
"temp_max": 285.3,
"pressure": 1025,
"humidity": 91,
"sea_level": 1025,
"grnd_level": 979
},
"visibility": 10000,
"wind": {
"speed": 0.89,
"deg": 245,
"gust": 2.24
},
"clouds": {
"all": 100
},
"dt": 1729444238,
"sys": {
"type": 2,
"id": 20633,
"country": "CZ",
"sunrise": 1729402572,
"sunset": 1729440356
},
"timezone": 7200,
"id": 3068160,
"name": "Pilsen",
"cod": 200
}

>Solution :

It looks to me like you are "double fixing" your key conversion. Either set your keyDecodingStrategy to .convertFromSnakeCase or provide CodingKeys that map your property names to their keys, but not both.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading