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?