在 Swift 中解码 JSON 数据

问题描述 投票:0回答:1

我正在尝试解码一些 JSON 数据,但遇到了 CodingKeys 问题。我能够毫无问题地解码整个 JSON,直到我添加带有编码键的枚举。

工作代码如下所示

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
}

当我将代码更改为这样时,它会停止解码

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
}


我的解码代码如下

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
    }

最后,JSON 数据如下所示

{
"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
}
json swift
1个回答
0
投票

在我看来,您正在“双重修复”您的密钥转换。将您的

keyDecodingStrategy
设置为
.convertFromSnakeCase
提供
CodingKeys
将您的属性名称映射到其键,但 不能两者兼而有之。

© www.soinside.com 2019 - 2024. All rights reserved.