当我只想获取字典中的特定值时,如何解码字典值的 JSON 数组?

Posted

技术标签:

【中文标题】当我只想获取字典中的特定值时,如何解码字典值的 JSON 数组?【英文标题】:How do I decode JSON array of dictionary values in when I only want to grab specific values in the dictionary? 【发布时间】:2020-01-26 03:52:30 【问题描述】:

我正在尝试从下面“列表”部分的 JSON 中获取特定信息。

JSON 示例


    city =     
        coord =         
            lat = "37.323";
            lon = "-122.0322";
        ;
        country = US;
        id = 5341145;
        name = Cupertino;
        population = 58302;
        sunrise = 1579965395;
        sunset = 1580001833;
        timezone = "-28800";
    ;
    cnt = 40;
    cod = 200;
    list =     (
                
            clouds =             
                all = 99;
            ;
            dt = 1580018400;
            "dt_txt" = "2020-01-26 06:00:00";
            main =             
                "feels_like" = "286.89";
                "grnd_level" = 1011;
                humidity = 78;
                pressure = 1020;
                "sea_level" = 1020;
                temp = "287.29";
                "temp_kf" = "-0.68";
                "temp_max" = "287.97";
                "temp_min" = "287.29";
            ;
            sys =             
                pod = n;
            ;
            weather =             (
                                
                    description = "overcast clouds";
                    icon = 04n;
                    id = 804;
                    main = Clouds;
                
            );
            wind =             
                deg = 183;
                speed = "0.77";
            ;
        ,
                
            clouds =             
                all = 88;
            ;
            dt = 1580029200;
            "dt_txt" = "2020-01-26 09:00:00";
            main =             
                "feels_like" = "286.55";
                "grnd_level" = 1011;
                humidity = 91;
                pressure = 1020;
                "sea_level" = 1020;
                temp = "286.64";
                "temp_kf" = "-0.51";
                "temp_max" = "287.15";
                "temp_min" = "286.64";
            ;
            rain =             
                3h = "1.88";
            ;
            sys =             
                pod = n;
            ;
            weather =             (
                                
                    description = "light rain";
                    icon = 10n;
                    id = 500;
                    main = Rain;
                
            );
            wind =             
                deg = 140;
                speed = "1.04";
            ;
        ,

但是,我对如何构造我的对象和解码 JSON 以获取我需要的值感到困惑。这是我的 Codable 类

class FiveDayWeatherInformation: Codable 

    struct Weather: Codable 
        var description: String
        var icon: String

        enum CodingKeys: String, CodingKey 
            case description
            case icon
        
    

    struct Main: Codable 
        var temp: Double

        enum CodingKeys: String, CodingKey 
            case temp
        
    

    struct ThreeHourItem: Codable 
        var dateText: String
        var weather: Weather
        var main: Main

        enum CodingKeys: String, CodingKey 
            case main
            case dateText = "dt_txt"
            case weather
        
    

    struct RootList: Codable 
        let list: [[String:ThreeHourItem]]

        enum CodingKeys: String, CodingKey 
            case list
        
    

    var rootList: RootList

    enum CodingKeys: String, CodingKey 
        case rootList = "list"
    

    required public init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.rootList = try values.decode(RootList.self, forKey: .rootList)
    

这是我尝试获取值的地方

    func fetchFiveDayForecastForCoordinates(latitude: CLLocationDegrees, longitude: CLLocationDegrees, completion: @escaping (_ weatherForecasts:[FiveDayWeatherInformation]?, Error?) -> Void) 
        // to do
        let url = URL(string: "http://api.openweathermap.org/data/2.5/forecast?lat=\(latitude)&lon=\(longitude)&APPID=APPID")
        let urlRequest = URLRequest(url: url!)
        let task = URLSession.shared.dataTask(with: urlRequest)  (data, response, error) in
            guard let data = data, error == nil else 
                completion(nil, APIError.apiServiceError)
                return
            

            do 
                let forecast = try JSONDecoder().decode(FiveDayWeatherInformation.RootList.self, from:data)
                print(forecast)
             catch 
                print(error)
            
        
        task.resume()
    

但是我不断收到此警告。

keyNotFound(CodingKeys(stringValue: "main", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "list", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), _JSONKey(stringValue: "clouds", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"main\", intValue: nil) (\"main\").", underlyingError: nil))

我相信我的 Codable 课程结构错误,但似乎无法弄清楚原因。

【问题讨论】:

发布完整的 json 响应 【参考方案1】:

list 中键 main 的值是一个数组。将结构更改为

struct RootList : Decodable 
    let list : [List]


struct List : Decodable 
    let main : Main
    let weather : [Weather]
    let dateText : String

    enum CodingKeys: String, CodingKey  case main, dateText = "dtTxt", weather 


struct Weather : Decodable 
    let icon : String
    let description: String


struct Main : Decodable 
    let temp : Double

密钥真的是dt_txt吗?我得到dtTxt

【讨论】:

嘿 Vadian,谢谢你的回答。我将如何访问不同结构中的值?我无法使用打印在 do-catch 块中的 forecast 对象访问它们。此外,如果我调用 let forecast = try JSONDecoder().decode(FiveDayWeatherInformation.Main.self, from:data),我会收到“没有与键关联的值”错误。 您必须始终解码根对象 (FiveDayWeatherInformation.RootList.self)。然后你用forecast.main.temp 得到温度。使用代码完成,编译器会显示哪些属性可用。

以上是关于当我只想获取字典中的特定值时,如何解码字典值的 JSON 数组?的主要内容,如果未能解决你的问题,请参考以下文章

C# - 字典 - 如何在字典中获取特定类值的最大值? [复制]

如何在字典中只显示几个值

如何使用swift获取字典中的索引值

如何删除Java中特定字符之前的所有字符?

MongoDB 和 Python - 带有列表的字典

如何制作包含特定值的 Swift 字典?