簡體   English   中英

如何在iOS Swift Codable中通過API響應通知或打印模型類中缺少的鍵?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM