在Swift 5中使用Codable解码JSON数组

时间:2019-04-24 13:38:54

标签: json swift alamofire

我花了很多时间在SO / web上看这些例子,但是我看不出我做错了什么。

我有一个REST服务器返回以下JSON:

{
        "data":{
            "customers":
            [
              {
                    "customerId":27,
                    "customerName":"Dispatch Tool Customer 1"
              }
            ]
        },
        "error":"<null>",
        "ok":1
    }

以及以下表示此数据的类:

public class ResponseBase : Codable
{
    public var ok : Int?
    public var error : String?
}

public class CustomersResponse : ResponseBase
{
    public class Customer : Codable
    {
        public var customerName : String?
        public var customerId : Int?

        enum CodingKeys: String, CodingKey {
            case customerId = "customerId"
            case customerName = "customerName"
        }

        required public init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            customerId = try values.decodeIfPresent(Int.self, forKey: .customerId)
            customerName = try values.decodeIfPresent(String.self, forKey: .customerName)
        }
    }

    public class Data : Codable
    {
        public var customers : [Customer]?

        enum CodingKeys: String, CodingKey {
            case customers = "customers"
        }

        required public init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            customers = try values.decodeIfPresent([Customer].self, forKey: .customers)
        }
    }

    public var data : Data?


    enum CodingKeys: String, CodingKey {
        case data = "data"
        case error = "error"
        case ok = "ok"
    }

    required public init(from decoder: Decoder) throws {
        super.init()
        data = try Data(from: decoder)
    }
}

以下代码使用Alamofire 4.0调用服务器,然后使用Swift中的JSON解码功能处理响应:

Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: [:]).responseJSON
            {
                response in
                print(response)
                print("=============================================================")

                do {
                    let decoder = JSONDecoder()

                    let model = try decoder.decode(CustomersResponse.self, from: response.data!)
                    print("done model")
                } catch let error {
                    print("ERROR")
                    print(error)
                }
            }

“ ok”和“ error”已正确解码。 “数据”也被解码,但是“客户”始终为零。最初,我有没有初始化程序和CodingKeys的类,但是,我当然得到了相同的结果。

我正在打印响应,我可以看到JSON正确下降了(尽管我不明白为什么它没有以标准JSON格式打印出来-为什么Alamofire为什么用[和:代替[ with =?来自服务器的JSON格式正确(JSON)。

我不确定我还能尝试什么。

2 个答案:

答案 0 :(得分:0)

这是对我有用的解决方案。感谢那些回答并指出我正确方向的人:

struct Customer: Decodable
{
    let customerId: Int?
    let customerName: String?
}


struct CustomerData : Decodable
{
    let customers : Array<Customer>?
}


struct ServerResponse<T:Decodable> : Decodable
{
    let data : T?
    let error : String?
    let ok : Bool?
}

typealias CustomersResponse = ServerResponse<CustomerData>

(注意:最初的问题中我有一个Int,但实际上是一个Bool)

答案 1 :(得分:-1)

首先,您正在使用Alamofire的json响应,这意味着结果已被转换为json对象或可可约定的字典。 通过使用可编码进行解码/编码,输入/输出值应为数据类型。这就是为什么您看到带有已解码内容的值的原因。

第二,我不确定您要实现什么目标,所以我将介绍最简单的格式。

struct Customer: Decodable{
    let customerId: Int
    let customerName: String
}

struct ServerResponse: Decodable {
    let ok: Int
    let error: String?
    let data: [Customer]
}

这是解码响应的最简单方法。对于ServerResponse,我也建议您使用Generic类型,而不是对其进行子类化,

struct ServerResponse<T>: Decodable {
    let ok: Int
    let error: String?
    let data: T
}
typealias CustomerResponse = ServerResponse<[Customer]>

解码任何服务器响应(仅当所有服务器响应格式正确时,才适用coz)