[英]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.