Как декодировать вложенный json в пользовательский класс с массивом в Swift? - PullRequest
0 голосов
/ 12 марта 2020

Я получаю nil при попытке проанализировать вложенный json ответ на пользовательский декодируемый класс ответа.

Пользовательские классы ответов:

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 Call,

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 равно нулю.

1 Ответ

1 голос
/ 12 марта 2020

Структуры, которые вы создали, (на мой взгляд) слишком сложны. Они могут быть следующими:

class User: Codable {

    var name: String
    var email: String
    var token: String
}

class ResponseData: Codable {

    let body: [User]?
}

class ResponseRoot: Codable {
    let data : ResponseData
}

Затем просто вызовите JSONDecoder().decode(ResponseRoot.self, from: data) внутри блока try catch.

...