为 JSON 创建模型,其中键是一个值
Creating model for JSON where key is a value
JSON :
{
"rows" :
[
{
"_id": "5cdc0ede5c3dcb04bdb3a972",
"emp_code": 187,
"log_id": 361711,
"punch_time": "2019-05-07T04:00:33.000Z",
"pin_type": 1,
"status": 4,
"__v": 0
},
{
"_id": "5cdc40de5c3dcb04bdb3a972",
"emp_code": 111,
"log_id": 361701,
"punch_time": "2019-05-07T04:00:35.000Z",
"pin_type": 101,
"status": 4,
"__v": 0
}
],
"pin_type_text": {
"1": "In Fingerprint",
"4": "In Card",
"101": "Out Fingerprint",
"104": "Out Card"
}
}
每行pin_type的值是指pin_type_text中与其对应的记录钥匙。
我正在使用 AlamofireObjectMapper 创建模型,这里是 PinTypeText 模型:
class PinTypeText : Mappable {
var inFingerprint: String?
var inCard: String?
var outFingerprint: String?
var outCard: String?
required init?(map: Map) {
}
func mapping(map: Map) {
self.inFingerprint <- map["1"]
self.inCard <- map["4"]
self.outFingerprint <- map["101"]
self.outCard <- map["104"]
}
}
问题 : 假设将来 pin_type 值 - 1, 4, 101, 104 在后端发生变化,如何在不更改模型的情况下处理这种情况。根据这个模型结构,每次后端模型改变时我都需要改变我的模型class
以下是如何使用 Codable
作为解决方案,
1. 创建一个模型 Row
,它将包含 json
的 rows
数组中单行的数据,即
class Row: Decodable {
var id: String?
var pinType: String?
var pinId: Int?
enum CodingKeys: String, CodingKey {
case id = "_id"
case pinId = "pin_type"
}
}
在上面的模型中,我使用了 2 个不同的属性 - pinType and pinId
。
pinId
将在 row
中包含 pin_type
值
pinType
将包含对应于 pinId
的实际值。我们稍后会填充这个值。
此外,我只使用了 row
的一小部分密钥。您可以根据需要添加更多。
2. 接下来创建另一个模型 Response
,它将包含 Row
的 array
,即
class Response: Decodable {
var rows: [Row]?
enum CodingKeys: String, CodingKey {
case rows, pin_type_text
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
rows = try values.decodeIfPresent([Row].self, forKey: .rows)
let pinTypeText = try values.decodeIfPresent([String:String].self, forKey: .pin_type_text)
rows?.forEach({ (row) in
if let pinId = row.pinId {
row.pinType = pinTypeText?[String(pinId)]
}
})
}
}
在上述模型中,
rows
json
中的数组被解析为 [Row]
.
pinTypeText
dictionary
被解析为 [String:String]
类型。
[Row]
被枚举以在每个 row
中使用 pinId
和 pinTypeText dictionary
.
[ 填充 pinType
=76=]
使用时需要使用pinType
属性一个Row
对象
response?.rows?.forEach({ print([=12=].pinType) }) //This line will print - "In Fingerprint" and "Out Fingerprint"
如果您在实施此方法时遇到问题,请告诉我。
JSON :
{
"rows" :
[
{
"_id": "5cdc0ede5c3dcb04bdb3a972",
"emp_code": 187,
"log_id": 361711,
"punch_time": "2019-05-07T04:00:33.000Z",
"pin_type": 1,
"status": 4,
"__v": 0
},
{
"_id": "5cdc40de5c3dcb04bdb3a972",
"emp_code": 111,
"log_id": 361701,
"punch_time": "2019-05-07T04:00:35.000Z",
"pin_type": 101,
"status": 4,
"__v": 0
}
],
"pin_type_text": {
"1": "In Fingerprint",
"4": "In Card",
"101": "Out Fingerprint",
"104": "Out Card"
}
}
每行pin_type的值是指pin_type_text中与其对应的记录钥匙。
我正在使用 AlamofireObjectMapper 创建模型,这里是 PinTypeText 模型:
class PinTypeText : Mappable {
var inFingerprint: String?
var inCard: String?
var outFingerprint: String?
var outCard: String?
required init?(map: Map) {
}
func mapping(map: Map) {
self.inFingerprint <- map["1"]
self.inCard <- map["4"]
self.outFingerprint <- map["101"]
self.outCard <- map["104"]
}
}
问题 : 假设将来 pin_type 值 - 1, 4, 101, 104 在后端发生变化,如何在不更改模型的情况下处理这种情况。根据这个模型结构,每次后端模型改变时我都需要改变我的模型class
以下是如何使用 Codable
作为解决方案,
1. 创建一个模型 Row
,它将包含 json
的 rows
数组中单行的数据,即
class Row: Decodable {
var id: String?
var pinType: String?
var pinId: Int?
enum CodingKeys: String, CodingKey {
case id = "_id"
case pinId = "pin_type"
}
}
在上面的模型中,我使用了 2 个不同的属性 - pinType and pinId
。
pinId
将在row
中包含 pinType
将包含对应于pinId
的实际值。我们稍后会填充这个值。
pin_type
值
此外,我只使用了 row
的一小部分密钥。您可以根据需要添加更多。
2. 接下来创建另一个模型 Response
,它将包含 Row
的 array
,即
class Response: Decodable {
var rows: [Row]?
enum CodingKeys: String, CodingKey {
case rows, pin_type_text
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
rows = try values.decodeIfPresent([Row].self, forKey: .rows)
let pinTypeText = try values.decodeIfPresent([String:String].self, forKey: .pin_type_text)
rows?.forEach({ (row) in
if let pinId = row.pinId {
row.pinType = pinTypeText?[String(pinId)]
}
})
}
}
在上述模型中,
rows
json
中的数组被解析为[Row]
.pinTypeText
dictionary
被解析为[String:String]
类型。
[ 填充[Row]
被枚举以在每个row
中使用pinId
和pinTypeText dictionary
.pinType
=76=]
使用时需要使用pinType
属性一个Row
对象
response?.rows?.forEach({ print([=12=].pinType) }) //This line will print - "In Fingerprint" and "Out Fingerprint"
如果您在实施此方法时遇到问题,请告诉我。