如何将嵌套 json 解码为带有 Swift 中的数组的自定义 class?
How to decode nested json on to a custom class with array in Swift?
我在尝试将嵌套的 json 响应解析为自定义可解码响应时收到 nil
class。
自定义响应类:
class User: Decodable, Encodable {
var name: String?
var email: String?
var token: String?
enum CodingKeys: String, CodingKey {
case name
case email
case token
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try? container.decode(String.self, forKey: .name)
self.email = try? container.decode(String.self, forKey: .email)
self.token = try? container.decode(String.self, forKey: .token)
}
}
class ResponseData: Decodable {
let body: [User]?
enum CodingKeys: String, CodingKey {
case users
case body
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let response = try container.nestedContainer(keyedBy:CodingKeys.self, forKey: .body)
self.body = try response.decode([User].self, forKey: .users)
}
}
class ResponseRoot: Decodable {
let data : ResponseData?
enum CodingKeys: String, CodingKey { case data }
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.data = try? container.decode(ResponseData.self, forKey: .data)
}
}
Json 解析响应,
{
"status": "success",
"errorMessage": null,
"data": {
"headers": {},
"body": [
{
"name": "Alex",
"email": "alex@b.c",
"password": "1234",
"token": "1234",
"loginStatus": 0
},
{
"name": "Einstein",
"email": "e@b.c",
"password": "1234",
"token": "A valid token",
"loginStatus": 1
}
],
"statusCode": "OK",
"statusCodeValue": 200
}
}
Alamofire 呼叫,
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.queryString, headers: nil)
.validate()
.responseJSON { response in
switch (response.result) {
case .success( _):
do {
let users = try JSONDecoder().decode(ResponseRoot.self, from: response.data!) // getting users = nil
completion((users.data?.body!)!)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
completion([])
}
case .failure(let error):
print("Request error: \(error.localizedDescription)")
completion([])
}
现在,let users = try JSONDecoder().decode(ResponseRoot.self, from: response.data!)
不会创建任何异常,但 users
为零。
您制作的结构(在我看来)过于复杂。它们可能是:
class User: Codable {
var name: String
var email: String
var token: String
}
class ResponseData: Codable {
let body: [User]?
}
class ResponseRoot: Codable {
let data : ResponseData
}
然后只需在 try catch 块中调用 JSONDecoder().decode(ResponseRoot.self, from: data)
。
我在尝试将嵌套的 json 响应解析为自定义可解码响应时收到 nil
class。
自定义响应类:
class User: Decodable, Encodable {
var name: String?
var email: String?
var token: String?
enum CodingKeys: String, CodingKey {
case name
case email
case token
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try? container.decode(String.self, forKey: .name)
self.email = try? container.decode(String.self, forKey: .email)
self.token = try? container.decode(String.self, forKey: .token)
}
}
class ResponseData: Decodable {
let body: [User]?
enum CodingKeys: String, CodingKey {
case users
case body
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let response = try container.nestedContainer(keyedBy:CodingKeys.self, forKey: .body)
self.body = try response.decode([User].self, forKey: .users)
}
}
class ResponseRoot: Decodable {
let data : ResponseData?
enum CodingKeys: String, CodingKey { case data }
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.data = try? container.decode(ResponseData.self, forKey: .data)
}
}
Json 解析响应,
{
"status": "success",
"errorMessage": null,
"data": {
"headers": {},
"body": [
{
"name": "Alex",
"email": "alex@b.c",
"password": "1234",
"token": "1234",
"loginStatus": 0
},
{
"name": "Einstein",
"email": "e@b.c",
"password": "1234",
"token": "A valid token",
"loginStatus": 1
}
],
"statusCode": "OK",
"statusCodeValue": 200
}
}
Alamofire 呼叫,
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.queryString, headers: nil)
.validate()
.responseJSON { response in
switch (response.result) {
case .success( _):
do {
let users = try JSONDecoder().decode(ResponseRoot.self, from: response.data!) // getting users = nil
completion((users.data?.body!)!)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
completion([])
}
case .failure(let error):
print("Request error: \(error.localizedDescription)")
completion([])
}
现在,let users = try JSONDecoder().decode(ResponseRoot.self, from: response.data!)
不会创建任何异常,但 users
为零。
您制作的结构(在我看来)过于复杂。它们可能是:
class User: Codable {
var name: String
var email: String
var token: String
}
class ResponseData: Codable {
let body: [User]?
}
class ResponseRoot: Codable {
let data : ResponseData
}
然后只需在 try catch 块中调用 JSONDecoder().decode(ResponseRoot.self, from: data)
。