Swift 可使用不同的字典类型数组编码

Swift Codable with Different Array of Dictionary Types

我有JSON个数据,它是一个字典数组,其中第一项与其余数组项不同。

样本JSON

[
  {
    "totalDays": 180,
    "totalWorkingDays": 148,
    "totalWorkingHours": "1184:00:00",
    "totalWorkedHours": "985:23:10",
    "totalShortageHours": "-199:37:50",
    "avgWorkingHours": "06:39:28(83%)",
    "avgShortageHours": "01:20:31(17%)",
    "totalAbsents": 13,
    "totalLeaves": 4
  },
  {
    "attendanceDayCount": 1,
    "attendanceDate": "21-Jan-19",
    "attendanceDay": "Monday"
  },
  {
    "attendanceDayCount": 2,
    "attendanceDate": "22-Jan-19",
    "attendanceDay": "Tuesday"
  },
  {
    "attendanceDayCount": 3,
    "attendanceDate": "23-Jan-19",
    "attendanceDay": "Wednesday"
  }
]

我正在使用 Codable,我的结构如下所示

struct DashboardSummary : Codable {
    
   var totalDays : Int?
   var totalWorkingDays : Int?
   var totalWorkingHours : String?
   var totalWorkedHours : String?
   var totalShortageHours : String?
   var avgWorkingHours : String?
   var avgShortageHours : String?
   var totalAbsents : Int?
   var totalLeaves : Int?
   
} 

struct DaySummary : Codable {

   var attendanceDayCount : Int?
   var attendanceDate : String?
   var attendanceDay : String?    

}

编辑:JSON 从网络请求方法解码

DispatchQueue.main.async {
   if let responseObject = try? JSONDecoder().decode(Response.self, from: data) {
     print("responseObject", responseObject)
     completion(.success(responseObject))
   }
   else {
     let error = NSError(domain: "", code: 200, userInfo: [NSLocalizedDescriptionKey : "Failed to decode"])
     completion(.failure(error))
   }
 }

我试过的东西

  1. 我通过我的网络请求将 'DashboardSummary' 结构传递为可编码,它确实给出了第一项的结果,当然数组的其余部分为零值。

  2. 我尝试了 init(from decoder: Decoder)func encode(to encoder: Encoder) 不幸的是对我不起作用。

我该如何解决这个问题?

首先,你需要创建一个third结构体来表示数组,例如:

struct Response : Codable {
    var dashboardSummary: DashboardSummary?
    var daySummaries: [DaySummary]
    
    enum CodingKeys: CodingKey {
        case dashboardSummary, daySummaries
    }
}

然后您需要实施 init(from:)encode(to:) 来进行自定义编码。

您可以使用 unkeyedContainer 到 decode/encode 它。解码的时候,你一直从容器while解码,容器不是isAtEnd.

init(from decoder: Decoder) throws {
    var container = try decoder.unkeyedContainer()
    dashboardSummary = try container.decodeIfPresent(DashboardSummary.self)
    daySummaries = []
    while !container.isAtEnd {
        daySummaries.append(try container.decode(DaySummary.self))
    }
}

func encode(to encoder: Encoder) throws {
    var container = encoder.unkeyedContainer()
    try container.encode(dashboardSummary)
    for daySummary in daySummaries {
        try container.encode(daySummary)
    }
}

如果您不打算更改这些属性,也可以考虑将其设置为常量。