我正在尝试在我正在开发的iOS应用程序中使用的API是JSON API。我正在使用一个库来解析服务器正在检索的数据。现在我尝试使用Swift引入的新Codable协议自己解析JSON。
我成功设法解析了data
和attributes
部分,但我遇到的困难在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
?
答案 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")
}
}