Codable Arrays 和 Alamofire 的问题

Posted

技术标签:

【中文标题】Codable Arrays 和 Alamofire 的问题【英文标题】:Issues with Codable Arrays and Alamofire 【发布时间】:2020-01-13 16:25:50 【问题描述】:

我正在尝试通过 Alamofire 提交以下请求,但收到以下错误:

2020-01-13 09:41:05.912103-0600 AFNetworkingDemo[29720:604258] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“JSON 写入中的类型无效 (__SwiftValue)”

我的假设是这是我在对象中定义数组的方式(我关注的是这里找到的一些材料:https://benscheirman.com/2017/06/swift-json)

struct ProgramRequest: Codable 
    var userID: Int
    var programData: ProgramData

    var json: Constants.Json 
        return [
            "userID": userID,
            "programData": programData.json,
        ]
    


struct ProgramData: Codable 
    var airhotel: [AirHotel]
    var security: [Security]

    var json: Constants.Json 
        return [
            "airhotel": airhotel,
            "security": security
        ]
    


struct AirHotel: Codable 
    var id: Int
    var loyaltyNumber: String

    var json: Constants.Json 
        return [
            "id": id,
            "loyaltyNumber": loyaltyNumber
        ]
    


struct Security: Codable 
    var vendorCode: String
    var loyaltyNumber: String

    var json: [String: Any] 
        return [
            "vendorCode": vendorCode,
            "loyaltyNumber": loyaltyNumber
        ]
    

每个级别的 json 字典是为 Alamofire 适当地渲染对象。对于给定的示例,如果我使用以下命令将其打印出来:

let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted

let jsonData = try jsonEncoder.encode(programRequest)

if let jsonString = String(data: jsonData, encoding: .utf8) 
    print(jsonString) #1


print("IsValidJSON: ", JSONSerialization.isValidJSONObject(programRequest)) #2

print(programRequest.json) #3

urlRequest = try! JSONEncoding.default.encode(urlRequest, with: programRequest.json) #4 causes error

1 个输出:


  "userID" : 10021,
  "programData" : 
    "airhotel" : [],
    "security" : [
    
        "vendorCode" : "sty",
        "loyaltyNumber" : "Loyal1"
    
    ]
  

2 输出 IsValidJSON: 假

3 输出 - 我注意到输出中的 AFNetworkingDemo.Security,是 Alamofire JSONEncoding 上的内容:

["programData": ["security": [AFNetworkingDemo.Security(vendorCode: "sty", loyaltyNumber: "Loyal1")], "airhotel": []], "userID": 10021]

我的问题是,我需要对 ProgramRequest 的 AirHotel 和 Security 部分进行哪些更改才能解决我与 Alamofire 相关的问题?

【问题讨论】:

这与 Alamofire 没有任何关系。我建议你看看 Codable 是如何工作的,因为你完全可以在没有 Alamofire 的情况下工作。此外,问题中没有使用 Alamofire。 Alamofire 通过调用返回错误信息:try! JSONEncoding.default.encode(urlRequest, with: programRequest.json)。关于 Codeable 的工作方式,我的问题是使用 Codable 和 AlamoFire 及其 JSONEncoding 机制。 是的,如果您想使用Encodable 参数,您必须更新到 Alamofire 5 或在 Alamofire 4 中编写自己的参数处理。 我目前正在使用 Alamofire 5 (5.0.0-rc.3)。 那么你需要使用JSONParameterEncoder,而不是JSONEncoding 【参考方案1】:

第 1 步:停止重新发明 Codable

json 计算属性不需要,使用不当。

删除它。

struct ProgramRequest: Codable 
    var userID: Int
    var programData: ProgramData


struct ProgramData: Codable 
    var airhotel: [AirHotel]
    var security: [Security]


struct AirHotel: Codable 
    var id: Int
    var loyaltyNumber: String


struct Security: Codable 
    var vendorCode: String
    var loyaltyNumber: String

第 2 步:开始使用 Codable

现在给定一个programRequest,例如。像这样

let programRequest = ProgramRequest(userID: 1, programData: ProgramData(airhotel: [AirHotel(id: 1, loyaltyNumber: "loyaltyNumber")], security: [Security(vendorCode: "loyaltyNumber", loyaltyNumber: "loyaltyNumber")]))

您可以简单地生成代表 JSON 的正确 Data 值

let data = try JSONEncoder().encode(programRequest)

并且(如果您愿意)您可以将数据转换为字符串

let json = String(data: data, encoding: .utf8)

输出

Optional("\"userID\":1,\"programData\":\"airhotel\":[\"id\":1,\"loyaltyNumber\":\"loyaltyNumber\"],\"security\":[\"vendorCode\":\"loyaltyNumber\",\"loyaltyNumber\":\"loyaltyNumber\"]")

就是这样

【讨论】:

问题是,Alamofire 通过语句 JSONEncoding.default.encode(urlRequest, with: data) 期待字典,即。我收到一条错误消息:无法将“ProgramRequest”类型的值转换为预期的参数类型“Parameters?” (又名“可选>”)。这就是对象层次结构的每一级都有 json 部分的原因。

以上是关于Codable Arrays 和 Alamofire 的问题的主要内容,如果未能解决你的问题,请参考以下文章

忽略 Codable 对象中的非 Codable 可选属性

Swift 使用Codable协议进行json转模型

Codable : 不符合协议'Decodable'

如何使 UIImage 符合 Codable?

使用 URLSession 和 Codable 解析 JSON 数据

如何使用 Codable 和 Swift 解析这个嵌套的 JSON?