首页 > 解决方案 > Swift Codable / Decodable with Nested json Array

问题描述

我是 swift 新手,正在尝试找出通过嵌套 Json 的方法。到目前为止,我已经尝试过 JSONSerialization 没有成功,但是在被建议切换到 Codable 之后,我试了一下,但我一直从解析的 JSON 中得到零。我到目前为止的代码:

struct AppData: Codable {
    let paymentMethods: [PaymentMethods]?
}
struct PaymentMethods: Codable {
    let payment_method: String?
}

AF.request(startAppUrl, method: .post, parameters: requestParams , encoding: JSONEncoding.default).responseString{
    response in
    switch response.result {
        case .success(let data):
            let dataStr = data.data(using: .utf8)!
            let parsedResult = try? JSONDecoder().decode( AppData.self, from: dataStr)
            print(parsedResult)

        case .failure(let error):
            print((error.localizedDescription))
    }
}

我的 JSON 数据可以在这里找到:https ://startv.co.tz/startvott/engine/jsonsample/ 。我正在使用 xcode 11

我将感谢您的帮助,因为它已经坚持了一周。

标签: jsonswiftcodable

解决方案


首先在请求行中替换responseStringresponseData,这避免了将字符串(返回)转换为数据的额外步骤。

其次,始终do - catch围绕一条JSONDecoder线添加一个块。永远不要忽略try?. 该块将捕获这个全面的DecodingError

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "paymentMethods", intValue: nil)], debugDescription: "预期解码 Array 但找到了一个字符串/数据。",底层错误: nil) )

该错误表明 key 的值paymentMethods不是数组。这是一个字符串。查看 JSON,它实际上是一个嵌套的 JSON 字符串,必须在第二级解码。

struct AppData: Codable {
    let paymentMethods: String
}
struct PaymentMethods: Codable {
    let paymentMethod: String
}

AF.request(startAppUrl, method: .post, parameters: requestParams , encoding: JSONEncoding.default).responseData{
    response in
    switch response.result {
        case .success(let data):
            do {
                let parsedResult = try JSONDecoder().decode( AppData.self, from: data)
                let paymentData = Data(parsedResult.paymentMethods.utf8)
                let secondDecoder = JSONDecoder()
                secondDecoder.keyDecodingStrategy = .convertFromSnakeCase
                let paymentMethods = try secondDecoder.decode([PaymentMethods].self, from: paymentData)
                print(paymentMethods)
            } catch {
                print(error)
            }

        case .failure(let error):
            print((error.localizedDescription))
    }
}

边注:

URL 不需要 POST 请求和参数。您可以省略除第一个参数之外的所有参数。


推荐阅读