json - 何时在 Swift 中使用动态编码/解码?
问题描述
我是 Swift 新手,对动态编码和解码有点困惑。
在一次采访中,我被要求解析 API 响应
API 响应:
{
"propertyID" : 12,
"user" : {
"firstname" : "James"
"lastname" : "William"
}
}
使用解码/编码我能够解析并输出答案。以下是我使用的类:
struct User: Codable {
let firstName: String?
let lastName: String?
enum CodingKeys: String, CodingKey {
case firstName
case lastName
}
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
firstName = try values.decode(String.self, forKey: .firstName)
lastName = try values.decodeIfPresent(String.self, forKey: .lastName)
}
}
和
struct Response : Codable {
let user: User?
let propertyID: Int?
enum CodingKeys: String, CodingKey {
case user
case propertyID
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
user = try values.decode(User.self, forKey: .user)
propertyID = try values.decode(Int.self, forKey: .propertyID)
}
}
但面试官回应:
“网络模型只能在没有任何编码键或初始化程序的情况下符合可解码/可编码,因为没有进行自定义编码/解码”。
请让我知道如何进一步改进上述类以及解析 json 的最佳实践。
解决方案
您的代码存在一些问题:
1:你应该问面试官“哪些属性可能是空的?” 并且只制作它们 optional
。你不应该做一切optional
。
2:struct
有一个自动@memberwise
初始化器,所以你不需要手动重写它。
3:您应该将decodeIfPresent
函数用于optional
您使用的任何值。
4:符合Decodable
自动添加需要的初始化器,不需要自定义就不需要重写了。面试官的观点
5:符合Decodable
或Encodable
自动在CodingKeys
下面加上变量的确切名称,所以你不需要再重写它只有当你不想改变它们时。
在这种情况下:
enum CodingKeys: String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
}
我会要求后端开发人员将原始 json 更改为正确的格式
您已将 non-camelCase 更改为camelCase,所以它是必需的!
6:符合Codable
让您也可以访问CodingKey
。因此,您可以根据需要在自定义初始化程序中使用它。
所以它可以很简单:
struct Response : Codable {
let user: User
let propertyID: Int
struct User: Codable {
let firstname: String
let lastname: String
}
}
请注意,您可以使用Response
struct 作为该结构的命名空间User
。
最后,请记住,这取决于公司的需求和开发人员指南。