[英]How to create a model class and access the values from JSON response using Codable in ios swift?
[英]How to notify or print for missing key on model class from API response in iOS Swift Codable?
我有一個來自API的JSON響應,如下所示,
以前的JSON響應:
[
{
"EmployeeId": 711,
"FirstName": "Steve",
"LastName": "Jobs"
},
{
"EmployeeId": 714,
"FirstName": "John",
"LastName": "Doe"
}
]
和model的模型類有以下代碼
class EmployeeModel: Codable {
let EmployeeId: Int?
let FirstName: String?
let LastName: String?
}
用Swift Codable解析工作正常
do {
let decodedResponse = try JSONDecoder().decode([EmployeeModel].self, from: response.rawData())
print(decodedResponse)
} catch let jsonErr {
print(jsonErr.localizedDescription)
}
但現在
最新的JSON響應
從API更改並添加一個MiddleName鍵作為響應,請參閱下面的屏幕截圖,它也可以正常使用Swift Codable代碼。
但是如何在iOS Swift 5中通過API的JSON響應添加通知或打印MiddleName鍵?
更新問題
根據@ CZ54下面提供的答案,解決方案工作正常,但無法檢查另一個派生類缺失鍵。 例如:
// MARK:- LoginModel
class LoginModel: Codable {
let token: String?
let currentUser: CurrentUser?
}
// MARK:- CurrentUser
class CurrentUser: Codable {
let UserName: String?
let EmployeeId: Int?
let EmployeeName: String?
let CompanyName: String?
}
您可以執行以下操作:
let json = """
{
"name" : "Jobs",
"middleName" : "Bob"
}
"""
class User: Decodable {
let name: String
}
extension JSONDecoder {
func decodeAndCheck<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable {
let result = try self.decode(type, from: data)
if let json = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as? [String: Any] {
let mirror = Mirror(reflecting: result)
let jsonKeys = json.map { return $0.0 }
let objectKeys = mirror.children.enumerated().map { $0.element.label }
jsonKeys.forEach { (jsonKey) in
if !objectKeys.contains(jsonKey) {
print("\(jsonKey) is not used yet")
}
}
}
return result
}
}
try JSONDecoder().decodeAndCheck(User.self, from: json.data(using: .utf8)!)
//will print "middleName is not use yet"
您可以實現initializer
並檢查key
是否存在,如下所示,
struct CustomCodingKey: CodingKey {
let intValue: Int?
let stringValue: String
init?(stringValue: String) {
self.intValue = Int(stringValue)
self.stringValue = stringValue
}
init?(intValue: Int) {
self.intValue = intValue
self.stringValue = "\(intValue)"
}
}
class EmployeeModel: Codable {
var EmployeeId: Int?
var FirstName: String?
var LastName: String?
private enum CodingKeys: String, CodingKey {
case EmployeeId, FirstName, LastName
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let allKeysContainer = try decoder.container(keyedBy: CustomCodingKey.self)
self.EmployeeId = try container.decodeIfPresent(Int.self, forKey: .EmployeeId)
self.FirstName = try container.decodeIfPresent(String.self, forKey: .FirstName)
self.LastName = try container.decodeIfPresent(String.self, forKey: .LastName)
let objectKeys = container.allKeys.map { $0.rawValue}
for key in allKeysContainer.allKeys {
if objectKeys.contains(key.stringValue) == false {
print("Key: " + key.stringValue + " is added!")
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.