我在我的iOS应用程序中使用NASA API来获取一些图像。我从服务器收到的响应如下:
{
"date": "2014-02-04T03:30:01",
"id": "LC8_L1T_TOA/LC81270592014035LGN00",
"resource": {
"dataset": "LC8_L1T_TOA",
"planet": "earth"
},
"service_version": "v1",
"url": "https://earthengine.googleapis.com/api/thumb?thumbid=bc77b079c8ecd07cd668c576c22b83a4&token=a16639b0d38dd68c586c24a6ee5299d9"
}
我的请求网址是:
https://api.nasa.gov/planetary/earth/imagery/?lon=100.75&lat=1.5&date=2014-02-01&api_key=DEMO_KEY
我解码此响应的结构是:
import Foundation
// MARK: - EarthImages
struct EarthImages: Codable {
let date: String
let id: String
let resource: Resource
let serviceVersion: String
let url: String
private enum CodingKeys: String, CodingKey {
case date = "date"
case id = "id"
case resource = "resource"
case serviceVersion = "service_version"
case url = "url"
}
}
问题是-当我尝试使用以下代码解码响应
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data {
do {
let earthImages = try JSONDecoder().decode(EarthImages.self, from: data)
print(earthImages.url)
}
catch let error{
print(error)
}}
}.resume()
我进入控制台。
keyNotFound(CodingKeys(stringValue: "date", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"date\", intValue: nil) (\"date\").", underlyingError: nil))
我使用PAW来检查是否得到正确的响应,并且它可以正常工作,因此问题很可能出在我的代码中。我该如何解决这个问题?
答案 0 :(得分:0)
看起来...还好吗? (假设Resource
也是Decodable
,但这将是一个单独的问题)。也许错误实际上是在告诉您事实,您可能正在尝试解码没有日期值的JSON Blob。
在我们尝试解码之前,您可以显式地看到我们正在尝试通过添加印刷品来解码的内容:
if let data = data {
print(String(data: data, encoding: .utf8)!)
do {
...
然后分开,如果不能保证每个响应中都存在date字段,则应将其设为可选:
struct EarthImages: Codable {
let date: String?
let id: String
let resource: Resource
let serviceVersion: String
let url: String
}
请注意,如果字符串枚举与枚举大小写完全相同,则无需重新声明:
enum CodingKeys: String, CodingKey {
case date // "date" is implied
case id
case resource
case serviceVersion = "service_version"
case url
}
另一个有趣的事实:JSONDecoder
也可以自动从蛇格转换而无需定义CodingKeys
(如果每个键都一致)。
所以您也可以这样做:
struct EarthImages: Codable {
let date: String
let id: String
let resource: Resource
let serviceVersion: String
let url: String
}
...
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let earthImages = try decoder.decode(EarthImages.self, from: data)
}