JSONDecoder 无法解析地图列表
JSONDecoder fails to parse a list of maps
我已经准备a simple test Playground at Github演示我的问题:
我的Swift代码:
struct TopResponse: Codable {
let results: [Top]
}
struct Top: Codable {
let uid: Int
let elo: Int
let given: String
let photo: String?
let motto: String?
let avg_score: String?
let avg_time: String?
}
let url = URL(string: "https://slova.de/ws/top")!
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
let decoder = JSONDecoder()
guard let data2 = data,
let tops = try? decoder.decode(TopResponse.self, from:
data2) else { return }
print(tops.results[4].given)
}
task.resume()
无法解析获取的 JSON 字符串并且不打印任何内容。
请问这里可能是什么问题?
你的代码有什么问题?
try?
这是罪魁祸首。
为什么?您忽略了 decode(_:from:)
抛出的错误。 您忽略了错误,它可以为您提供确切的原因或至少提示失败的原因。相反,写一个正确的 do { try ... } catch { ... }
.
所以:
guard let data2 = data,
let tops = try? decoder.decode(TopResponse.self, from:
data2) else { return }
print(tops.results[4].given)
=>
guard let data2 = data else { return }
do {
let tops = try decoder.decode(TopResponse.self, from: data2)
print(tops.results[4].given)
} catch {
print("Got error while parsing: \(error)")
print("With response: \(String(data: data2, encoding: .utf8))") //Just in case because I've seen plenty of code where expected JSON wasn't the one received: it was an error, doc changed, etc...
}
第一次打印的输出:
$>Got error while parsing: keyNotFound(CodingKeys(stringValue: "results", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"results\", intValue: nil) (\"results\").", underlyingError: nil))
修复:
struct TopResponse: Codable {
let results: [Top]
enum CodingKeys: String, CodingKey {
case results = "data"
}
}
或将 results
重命名为 data
。
然后,下一个错误:
$>Got error while parsing: typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "avg_score", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))
摘自JSON:
"avg_score": 20.4
不是String
(不在双引号之间的值),而是Double
.
修复:
let avg_score: String?
=>
let avg_score: Double?
我已经准备a simple test Playground at Github演示我的问题:
我的Swift代码:
struct TopResponse: Codable {
let results: [Top]
}
struct Top: Codable {
let uid: Int
let elo: Int
let given: String
let photo: String?
let motto: String?
let avg_score: String?
let avg_time: String?
}
let url = URL(string: "https://slova.de/ws/top")!
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
let decoder = JSONDecoder()
guard let data2 = data,
let tops = try? decoder.decode(TopResponse.self, from:
data2) else { return }
print(tops.results[4].given)
}
task.resume()
无法解析获取的 JSON 字符串并且不打印任何内容。
请问这里可能是什么问题?
你的代码有什么问题?
try?
这是罪魁祸首。
为什么?您忽略了 decode(_:from:)
抛出的错误。 您忽略了错误,它可以为您提供确切的原因或至少提示失败的原因。相反,写一个正确的 do { try ... } catch { ... }
.
所以:
guard let data2 = data,
let tops = try? decoder.decode(TopResponse.self, from:
data2) else { return }
print(tops.results[4].given)
=>
guard let data2 = data else { return }
do {
let tops = try decoder.decode(TopResponse.self, from: data2)
print(tops.results[4].given)
} catch {
print("Got error while parsing: \(error)")
print("With response: \(String(data: data2, encoding: .utf8))") //Just in case because I've seen plenty of code where expected JSON wasn't the one received: it was an error, doc changed, etc...
}
第一次打印的输出:
$>Got error while parsing: keyNotFound(CodingKeys(stringValue: "results", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"results\", intValue: nil) (\"results\").", underlyingError: nil))
修复:
struct TopResponse: Codable {
let results: [Top]
enum CodingKeys: String, CodingKey {
case results = "data"
}
}
或将 results
重命名为 data
。
然后,下一个错误:
$>Got error while parsing: typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "avg_score", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))
摘自JSON:
"avg_score": 20.4
不是String
(不在双引号之间的值),而是Double
.
修复:
let avg_score: String?
=>
let avg_score: Double?