首页 > 解决方案 > Alamofire + Decodable - 如何将 responseJSON 转换为 NSData

问题描述

我很确定我的问题很容易解决,但我找不到任何解决方案。所以我有 Alamofire 请求并且在处理数据类型时遇到了麻烦。我有很多“打印出来”只是为了检查我一步一步得到的数据。

Alamofire.request(URL, method: .get, headers: headers).responseJSON { response in
            switch responseJSON.result {
            case .success(let value):
                print(type(of: value))  //__NSDictionaryI
                print(value)
                print(type(of:responseJSON))  //DataResponse<Any>
                print(responseJSON) . //SUCCESS: {"billing_addresses" =     (...
                print(responseJSON.value as Any) . //Optional({...
                //print(responseJSON.value as! [[String:Any]]) . //Could not cast value of type '__NSDictionaryI' (0x10b9fb508) to 'NSArray' (0x10b9fb008).

                do {
                    let decoder = JSONDecoder()
                    let model = try decoder.decode(Info.self, from: value as! Data) //Decode JSON Response Data
                    print(model.id)
                } catch let parsingError {
                    print("Error", parsingError)
                }

现在我有一个错误:**Could not cast value of type '__NSSingleEntryDictionaryI' (0x10d240f78) to 'NSData' (0x10d241090).**

responseJSON 的值为:

(我不确定这个值是否正确,因为当我签入 Postman 时,所有字符串都是双引号,并且“is_default”的值为真/假,而不是 0/1。但在 Xcode 中我有这个在控制台中。所以也许 responseJSON 有问题?..)

并且可能有零地址或多个地址。

{
"id": 40128,
"username": "test6",
"email": "test6@on.com",
"billing_addresses": [
    {
        "address_name": null,
        "country_code": "US",
        "first_name": "Ted",
        "last_name": "Qqqq",
        "company_name": "",
        "address_line1": "308 Sea Lane",
        "address_line2": "",
        "city": "QQQQ",
        "state": "FL",
        "postcode": "32000",
        "email_address": "test6@on.com",
        "phone_number": "11111111",
        "is_default_for_billing": true
    }
],
"shipping_addresses": [
    {
        "address_name": null,
        "country_code": "US",
        "first_name": "Ted",
        "last_name": "Qqqq",
        "company_name": "",
        "address_line1": "308 Sea Lane",
        "address_line2": "",
        "city": "QQQQ",
        "state": "FL",
        "postcode": "32000",
        "is_default_for_shipping": true
    }
]

}

这是模型

struct Info : Decodable {
                    let id: Int
                    let email: String
                    let username: String
                    let billing_addresses: Billings
                    let shipping_addresses: Shippings
                }
                struct Billings: Decodable{
                    let address_name: String
                    let country_code: String
                    let first_name: String
                    let last_name: String
                    let company_name: String
                    let address_line1: String
                    let address_line2: String
                    let city: String
                    let state: String
                    let postcode: String
                    let email_address: String
                    let phone_number: String
                    let is_default_for_billing: Bool

                }
                struct Shippings:Decodable{
                    let address_name: String
                    let country_code: String
                    let first_name: String
                    let last_name: String
                    let company_name: String
                    let address_line1: String
                    let address_line2: String
                    let city: String
                    let state: String
                    let postcode: String
                    let is_default_for_shipping: Bool

                }

如果我尝试将 SwiftyJSON 与as 参数一起使用,我会遇到一个不可能value的错误,我真的不知道该怎么办。AnyData

标签: alamofireswift4decodablejsondecoder

解决方案


responseJSON.result.value返回反序列化的集合类型,在您的情况下为字典[String:Any]

要使用JSONDecoder,您需要原始数据response.data

let model = try decoder.decode(Info.self, from: response.data) //Decode JSON Response Data

考虑到您将遇到解码错误:billing_addresses并且shipping_addresses是数组

let billing_addresses: [Billings] 
let shipping_addresses: [Shippings] // better name both structs in singular form (Billing, Shipping)

一些值可能是数字而不是字符串。

无论如何,建议使用convertFromSnakeCase密钥解码策略来摆脱丑陋的snake_case 名称。

编辑:

这是带有驼峰名称和单数形式的结构,您必须添加

decoder.keyDecodingStrategy = .convertFromSnakeCase

struct Info : Decodable {
    let id: Int
    let email: String
    let username: String
    let billingAddresses: [Billing]
    let shippingAddresses: [Shipping]
}

struct Billing : Decodable {
    let addressName: String?
    let countryCode, firstName, lastName, companyName: String
    let addressLine1, addressLine2, city, state, postcode: String
    let emailAddress, phoneNumber: String
    let isDefaultForBilling: Bool

}
struct Shipping : Decodable {
    let addressName: String?
    let countryCode, firstName, lastName, companyName: String
    let addressLine1, addressLine2, city, state, postcode: String
    let isDefaultForShipping: Bool
}

推荐阅读