使用Codable协议

时间:2017-11-13 14:59:02

标签: json swift json-api codable

我正在尝试在我正在开发的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"

    }

}

以存储为User对象检索的数据。

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

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类中的对象 - 在这种情况下role类型为RoleCodable

1 个答案:

答案 0 :(得分:0)

这不是很优雅,但这是我的操作方式,它涉及到init(from decoder: Decoder)的手动UserDecodable功能。基本上,我在“包含”部分中读了两次:第一次收集类型信息,第二次构建具有正确类型的关系。

我将键.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)

第二次,我们遍历“ included” JSON数组,同时在同一索引处检查ResourceIdentifierObject中的类型并手动建立每个关系(我添加了注释关系以演示不同的关系):< / p>

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")
    }
}