【问题标题】:Decode the included part from JSON API using the Codable protocol使用 Codable 协议从 JSON API 解码包含的部分
【发布时间】:2018-04-26 07:24:45
【问题描述】:

我正在开发的 iOS 应用程序中尝试使用的 API 是 JSON API。我正在使用一个库来解析服务器正在检索的数据。现在我正在尝试使用 Swift 引入的新 Codable 协议自己解析 JSON。

我成功地解析了dataattributes 部分,但我面临的困难在于included 部分。

首先我创建了这个类:

class UserCodable: Codable {

var data: UserCodableData?
var relationships: UserRelationships?

    enum CodingKeys: String, CodingKey {

        case data
        case relationships = "included"

    }

}

为了存储为用户对象检索到的数据。

与这个类一起,我创建了这两个结构

struct UserCodableData: Codable {

    var id: String?
    var type: String?
    var attributes: UserAttributes?

}

struct UserAttributes: Codable {

    var id: String?
    var type: String?
    var firstName: String?
    var lastName: String?
    var email: String?
    var officePhone: String?
    var mobilePhone: String?
    var timeZone: String?
    var active: Int?
    var middleName: String?
    var `extension`: String?
    var homePhone: String?
    var avatar: String?

    enum CodingKeys: String, CodingKey {

        case id
        case type
        case firstName = "firstname"
        case lastName = "lastname"
        case email
        case officePhone = "office_phone"
        case mobilePhone = "mobile_phone"
        case timeZone = "time_zone"
        case active
        case middleName = "middlename"
        case `extension`
        case homePhone = "home_phone"
        case avatar

    }

}

为了适当地存储数据和属性。

最后我创建了关于关系的结构(包括在内):

struct UserRelationships: Codable {

    var role: RoleCodable?

}

RoleCodable 类遵循相同的模式。

检索到的有关包含键的数据如下:

"data": {

     },
"included": [
    {
        "id": "10",
        "type": "roles",
        "attributes": {
            "title": "Role"
        }
    }
],

问题在于included 部分包含一个 JSON 对象数组。 如何解码和初始化 UserRelationships 类中的对象 - 在本例中为 RoleCodable 类型的 role

【问题讨论】:

    标签: json swift json-api codable


    【解决方案1】:

    这并不优雅,但我就是这样做的,它涉及UserDecodable 的手动init(from decoder: Decoder) 函数。基本上我在“包含”部分阅读了两次:第一次是收集类型信息,第二次是用正确的类型构建关系。

    我将密钥 .included 用于“包含”而不是 .relationships,因为“关系”作为 JSON API 响应中的另一个部分出现,可能会导致混淆。

    这是类型信息的容器,您可以将其重复用于任何包含的关系:

    struct ResourceIdentifierObject: Codable {
        let type: String
        let id: String
    
        enum CodingKeys: String, CodingKey {
            case type
            case id
        }
    }
    

    这是第一次阅读:

    let resourceIds = try data.decode([ResourceIdentifierObject].self,
                                      forKey: .included)

    我们第二次遍历“包含”JSON 数组,同时检查同一索引处 ResourceIdentifierObject 中的类型并手动构建每个关系(我添加了一个 cmets 关系来演示不同的关系):

    var included = try data.nestedUnkeyedContainer(forKey: .included)
    
    while !included.isAtEnd {
        let resourceId = resourceIds[included.currentIndex]
        switch resourceId.type {
        case "roles":
            role = try included.decode(RoleCodable.self)
        case "comments":
            comments.append(try included.decode(CommentCodable.self))
        default:
            print("unexpected type")
        }
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-11
      相关资源
      最近更新 更多