我目前正在尝试解码如下所示的 JSON:
{
"result": {
"success": true,
"items": [
{
"timeEntryID": "1",
"start": "1519558200",
"end": "1519563600",
"customerName": "Test-Customer",
"projectName": "Test-Project",
"description": "Entry 1",
},
{
"timeEntryID": "2",
"start": "1519558200",
"end": "1519563600",
"customerName": "Test-Customer",
"projectName": "Test-Project",
"description": "Entry 2",
}
],
"total": "2"
},
"id": "1"
}
这种特定类型的 JSON 的解码过程非常简单。我只需要这样的东西:
struct ResponseKeys: Decodable {
let result: ResultKeys
struct ResultKeys: Decodable {
let success: Bool
let items: [Item]
}
}
现在我面临的问题是服务器的每个响应都具有与上述 JSON 相同的结构,但具有不同的项目类型。所以有时是这样,但如果我调用 User 端点let items: [Item]
也可能是这样。let items: [User]
因为如果我只需修改 items 数组就为每个端点编写上述 swift 代码,这将是不必要的代码重复,我创建了一个自定义解码器:
enum KimaiAPIResponseKeys: String, CodingKey {
case result
enum KimaiResultKeys: String, CodingKey {
case success
case items
}
}
struct Activity: Codable {
let id: Int
let description: String?
let customerName: String
let projectName: String
let startDateTime: Date
let endDateTime: Date
enum CodingKeys: String, CodingKey {
case id = "timeEntryID"
case description
case customerName
case projectName
case startDateTime = "start"
case endDateTime = "end"
}
}
extension Activity {
init(from decoder: Decoder) throws {
let resultContainer = try decoder.container(keyedBy: KimaiAPIResponseKeys.self)
let itemsContainer = try resultContainer.nestedContainer(keyedBy: KimaiAPIResponseKeys.KimaiResultKeys.self, forKey: .result)
let activityContainer = try itemsContainer.nestedContainer(keyedBy: Activity.CodingKeys.self, forKey: .items)
id = Int(try activityContainer.decode(String.self, forKey: .id))!
description = try activityContainer.decodeIfPresent(String.self, forKey: .description)
customerName = try activityContainer.decode(String.self, forKey: .customerName)
projectName = try activityContainer.decode(String.self, forKey: .projectName)
startDateTime = Date(timeIntervalSince1970: Double(try activityContainer.decode(String.self, forKey: .startDateTime))!)
endDateTime = Date(timeIntervalSince1970: Double(try activityContainer.decode(String.self, forKey: .endDateTime))!)
}
}
"items"
如果仅包含单个对象而不包含数组,则解码器可以完美运行:
{
"result": {
"success": true,
"items":
{
"timeEntryID": "2",
"start": "1519558200",
"end": "1519563600",
"customerName": "Test-Customer",
"projectName": "Test-Project",
"description": "Entry 2",
},
"total": "2"
},
"id": "1"
}
如果items
是一个数组,我会收到以下错误:
typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [__lldb_expr_151.KimaiAPIResponseKeys.result], debugDescription: "期望解码 Dictionary 但找到了一个数组。",底层错误: nil))
我只是不知道如何修改我的解码器以处理一系列项目。我使用 JSON 的工作版本和非工作版本创建了一个 Playground 文件。请看一下并尝试一下:Decodable.playground
谢谢您的帮助!