【问题标题】:Swift: JSONDecoder returning nil from APISwift:JSONDecoder 从 API 返回 nil
【发布时间】:2019-09-16 22:03:36
【问题描述】:

目前正在通过一个从 OpenWeatherMap API 获取和解码数据的应用程序工作,目前除了让解码器返回某些内容外,我已经完成了所有工作。目前,解码器返回 nil,但是,我从 API 调用中获取数据字节。我不确定可能是什么问题。我已经根据层次结构设置了 ViewModel 结构。 OPW API JSON 数据似乎是字典键:值对集合类型的格式,键用引号括起来,是不是我的解码器因为引号而没有找到必要的信息?

获取和解码 API 调用...

@IBAction func saveCityButtonPressed() {

    if let city = cityNameTextField.text {
        let weatherURL = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(city)&APPID=8bad8461edbaf3ff50aa2f2fd8ad8a71&units=imperial")!

        let weatherResource = Resource<WeatherViewModel>(url: weatherURL) { data in
            let weatherVM = try? JSONDecoder().decode(WeatherViewModel.self, from: data)
            return weatherVM
        }
        Webservice().load(resource: weatherResource) { result in
        }
    }
}

视图模型

struct WeatherListViewModel {
private var weatherViewModels = [WeatherViewModel]()
}

struct WeatherViewModel: Decodable {
let name: String
let main: TemperatureViewModel
}

struct TemperatureViewModel: Decodable {
let temp: Double
let temp_min: Double
let temp_max: Double
}

JSON 数据示例:

{
    "coord":{
       "lon":-0.13,
       "lat":51.51
    },
    "weather":[
        {
             "id":300,
             "main":"Drizzle",
             "description":"light intensity drizzle","icon":"09d"
        }
    ],
    "base":"stations",
    "main":{
        "temp":280.32,
        "pressure":1012,
        "humidity":81,
        "temp_min":279.15,
        "temp_max":281.15
     },
     "visibility":10000,
     "wind":{
         "speed":4.1,
         "deg":80
     },
     "clouds":{
         "all":90
     },
     "dt":1485789600,
     "sys":{
         "type":1,
         "id":5091,
         "message":0.0103,
         "country":"GB",
         "sunrise":1485762037,
         "sunset":1485794875
     },
     "id":2643743,
     "name":"London",
     "cod":200
 }

【问题讨论】:

  • let weatherVM = try? JSONDecoder().decode(WeatherViewModel.self, from: data) 是愚蠢的。相反,使用try,将它包装在一个do/catch 结构中,catch 错误,然后打印出来!然后您将立即看到问题所在,因为会显示一个巨大的详细错误消息。
  • 不要try?从不 try? 在使用 Decodable 解码 JSON 时。 catch 错误,它会告诉你到底出了什么问题。提示:根对象中没有citymain
  • 就在这里。这是你愚蠢地、故意地扔掉的有用信息! Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "city", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"city\", intValue: nil) (\"city\").", underlyingError: nil))
  • 感谢 matt 和 vadian,我现在就试试。我正在关注一个讲座项目,这是我遇到的一个问题,幸好我向 SO 寻求帮助。
  • 抱歉:JSON 中有一个 main 键。 cityforecast 相关(与 weather 不同)API

标签: json swift decoder


【解决方案1】:

您的 WeatherViewModel 属性 city 是一个字符串,但您的 JSON 中没有 "city" 键。

【讨论】:

  • 哦等等,city 属性不应该在那里,应该是 name。
  • 我的错误,它不应该是城市,属性应该是名称。我在玩代码,忘了改回来,但是,即使使用 name 属性,我仍然得到 nil,我要编写 do/catch 块并查看错误消息是什么。
【解决方案2】:

通过将 JSONDecoder().decode 的结果设为可选 (try?),您可以确保在解码出错时获得 nil。您可以通过实施适当的 catch 块来快速捕获与解码相关的问题。例如:

do {
    let decoder = JSONDecoder()
    let messages = try decoder.decode(WeatherViewModel.self, from: data)
    print(messages as Any)
} catch DecodingError.dataCorrupted(let context) {
    print(context)
} catch DecodingError.keyNotFound(let key, let context) {
    print("Key '\(key)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch DecodingError.valueNotFound(let value, let context) {
    print("Value '\(value)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch DecodingError.typeMismatch(let type, let context) {
    print("Type '\(type)' mismatch:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch {
    print("error: ", error)
}

不是直接回答您的问题,但肯定会减少其他人了解解码的哪一部分出错的时间。

【讨论】:

  • 这应该是答案!感谢您抽出宝贵时间做出如此全面的回复。
【解决方案3】:
Why do we get nil value, when decoding the value?

Reasons:
 The response parameter may be the first letter as capital.
Solution: 
The coding keys concept is to out to nil value.
example:

struct Example{
var a: string
var b: string

enum Codingkeys: String,CodingKey{
case a = "a"
case b = "b"
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多