简体   繁体   中英

Swift Codable / Decodable with Nested json Array

I am new to swift and am trying to figureout passing Nested Json. So far I have tried JSONSerialization without success but after being advised to switch to Codable I have give it a try but I keep getting nill from parsed JSON. Code I have so far:

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))
    }
}

My JSON data can be found here: https://startv.co.tz/startvott/engine/jsonsample/ . I am using xcode 11

I will appreciate assistance as its already one week stuck on this.

First of all replace responseString with responseData in the request line, this avoids the extra step to convert string (back) to data.

Second of all add always a do - catch block around a JSONDecoder line. Never ignore decoding errors with try? . The block will catch this comprehensive DecodingError :

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "paymentMethods", intValue: nil)], debugDescription: "Expected to decode Array but found a string/data instead.", underlyingError: nil))

The error states that the value for key paymentMethods is not an array. It's a string. Looking at the JSON it's in fact a nested JSON string which must be decoded on a second level.

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))
    }
}

Side note:

The URL doesn't require a POST request and parameters. You can omit all parameters except the first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM