首页 > 解决方案 > 何时在 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 的最佳实践。

标签: jsonswiftxcodeparsing

解决方案


您的代码存在一些问题:

1:你应该问面试官“哪些属性可能是空的?” 并且只制作它们 optional。你不应该做一切optional

2:struct有一个自动@memberwise初始化器,所以你不需要手动重写它。

3:您应该将decodeIfPresent函数用于optional您使用的任何值。

4:符合Decodable自动添加需要的初始化器,不需要自定义就不需要重写了。面试官的观点

5:符合DecodableEncodable自动在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
    }
}

请注意,您可以使用Responsestruct 作为该结构的命名空间User

最后,请记住,这取决于公司的需求和开发人员指南。


推荐阅读