我有一個 API,它回傳這樣的有效負載(示例中只包含一個專案)。
{
"length": 1,
"maxPageLimit": 2500,
"totalRecords": 1,
"data": [
{
"date": "2021-05-28",
"peopleCount": 412
}
]
}
我知道我實際上可以創建一個像
struct Root: Decodable {
let data: [DailyCount]
}
struct DailyCount: Decodable {
let date: String
let peopleCount: Int
}
對于不同的呼叫,相同的 API 為根回傳相同的格式,但資料則不同。此外,我不需要根資訊 ( length, totalRecords, maxPageLimit)。所以,我正在考慮在其中創建一個自定義 init,struct DailyCount以便我可以在我的 URL 會話中使用它
let reports = try! JSONDecoder().decode([DailyCount].self, from: data!)
使用 Swift 5 我試過這個:
struct DailyCount: Decodable {
let date: String
let peopleCount: Int
}
extension DailyCount {
enum CodingKeys: String, CodingKey {
case data
enum DailyCountCodingKeys: String, CodingKey {
case date
case peopleCount
}
}
init(from decoder: Decoder) throws {
// This should let me access the `data` container
let container = try decoder.container(keyedBy: CodingKeys.self
peopleCount = try container.decode(Int.self, forKey: . peopleCount)
date = try container.decode(String.self, forKey: .date)
}
}
不幸的是,它不起作用。我有兩個問題:
- 該結構似乎不再符合
Decodable協議 - 所述
CodingKeys不包含peopleCount(因此回傳一個錯誤)
uj5u.com熱心網友回復:
由于多種原因,這不起作用。您正在嘗試解碼一個陣列,因此根本不會呼叫 DailyCount 的自定義解碼實作(如果要編譯),因為在頂層您的 JSON 包含一個物件,而不是一個陣列。
但是有一個更簡單的解決方案,它甚至不需要自己實作 Decodable。
您可以為外部物件創建一個通用包裝器結構,并將其與您需要的任何有效負載型別一起使用:
struct Wrapper<Payload: Decodable>: Decodable {
var data: Payload
}
然后,您可以使用它來解碼 DailyCount 結構陣列:
let reports = try JSONDecoder().decode(Wrapper<[DailyCount]>.self, from: data).data
通過在 JSONDecoder 上創建擴展,這可以變得更加透明:
extension JSONDecoder {
func decode<T: Decodable>(payload: T.Type, from data: Data) throws -> T {
try decode(Wrapper<T>.self, from: data).data
}
}
uj5u.com熱心網友回復:
Sven 的回答是純粹而優雅的,但如果我沒有指出還有一個愚蠢但簡單的方法,我將是失職:不要想太多,只是完全"data"不使用 Codable。例子:
// preconditions
let json = """
{
"length": 1,
"maxPageLimit": 2500,
"totalRecords": 1,
"data": [
{
"date": "2021-05-28",
"peopleCount": 412
}
]
}
"""
let jsonData = json.data(using: .utf8)!
struct DailyCount: Decodable {
let date: String
let peopleCount: Int
}
// okay, here we go
do {
let dict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [AnyHashable:Any]
let arr = dict?["data"] as? Array<Any>
let json2 = try JSONSerialization.data(withJSONObject: arr as Any, options: [])
let output = try JSONDecoder().decode([DailyCount].self, from: json2)
print(output) // yep, it's an Array of DailyCount
} catch {
print(error)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/400481.html
