【问题标题】:Codable Error - Expected to decode Dictionary<String, Any> but found an array instead可编码错误 - 应解码 Dictionary<String, Any> 但找到了一个数组
【发布时间】:2018-10-30 13:51:50
【问题描述】:

我正在尝试在 codable 的帮助下解码 JSON - https://pastebin.com/Xfjj2XiP

但是,当我这样做时,我得到了这个错误。

typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "txt_forecast", intValue: nil)], debugDescription: "预期解码 Dictionary 但找到了一个数组。”,基础错误:无))

这是我正在使用的代码:

struct container: Decodable {
    var days: [forecastDay]

    //Coding keys
    enum CodingKeys: String, CodingKey {
        case forecast = "forecast"
        case txt_forecast = "txt_forecast"
        case forecastday = "forecastday"
    }

    // Decoding
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let forecast = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .forecast)
        let txt_forecast = try forecast.nestedContainer(keyedBy: CodingKeys.self, forKey: .txt_forecast)
        let forecastdays = try txt_forecast.nestedContainer(keyedBy: CodingKeys.self, forKey: .forecastday)

        let forecastdaysData = try forecastdays.decode(String.self, forKey: .forecastday)

        days = try JSONDecoder().decode([forecastDay].self, from: forecastdaysData.data(using: .utf8)!)

        print(days)

    }
}

struct forecastDay: Decodable {
    var period: Int?
    var icon: String?
    var title: String?
    var fcttext: String?

    //Coding keys
    enum CodingKeys: String, CodingKey {
            case period = "period"
            case icon = "icon"
            case title = "title"
            case fcttext = "fcttext"
    }

    // Decoding
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        period = try container.decode(Int.self, forKey: .period)

        icon = try container.decode(String.self, forKey: .icon)

        title = try container.decode(String.self, forKey: .title)

        fcttext = try container.decode(String.self, forKey: .fcttext)
    }
}

【问题讨论】:

    标签: swift codable


    【解决方案1】:

    forecastDay 中的变量名称与 JSON 中的键没有区别,init(from decoder:) 也不做任何自定义,因此可以简化预测日期间的结构。

    struct ForecastDayPeriod: Decodable {
        let period: Int
        let icon: String
        let title: String
        let fcttext: String
    }
    

    现在最好为 JSON 中的每个级别使用带有键的枚举。此外,init(from decoder:) 不应创建新的JSONDecoder

    struct ForecastDay: Decodable {
    
        let periods: [ForecastDayPeriod]
    
        enum CodingKeys: String, CodingKey {
            case forecast
        }
    
        enum ForecastKeys: String, CodingKey {
            case txtForecast = "txt_forecast"
        }
    
        enum TxtForecastKeys: String, CodingKey {
            case forecastday
        }
    
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            let forecast = try values.nestedContainer(keyedBy: ForecastKeys.self,
                                                      forKey: .forecast)
            let txtForecast = try forecast.nestedContainer(keyedBy: TxtForecastKeys.self,
                                                           forKey: .txtForecast)
    
            periods = try txtForecast.decode([ForecastDayPeriod].self,
                                             forKey: .forecastday)        
        }
    
    }
    

    现在应该可以从 pastebin 示例中解码 JSON。

    do {
        let jsonData: Data = ...
        let forecastDay = try JSONDecoder().decode(ForecastDay.self, from: jsonData)
    } catch {
        print("Error: \(error)")
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多