0

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.

5
  • Your json does not seem valid: jsonformatter.org/json-pretty-print Commented Nov 15, 2019 at 10:13
  • The point of Codable is that the data structure has to mirror the structure of the json data and, unless using Codingkeys to remap fields, have the same field names as the json. You can use a custom init(with decoder:) to handle situations where there are anomalies, but in your case the data structure is not even close to the json layout. Commented Nov 15, 2019 at 10:13
  • @flanker this is just a portion of the JSON. Structure i too big to post it all here. I am retrieving JSON array at key paymentMethod Commented Nov 15, 2019 at 10:19
  • 3
    Don't try? in a JSONDecoder() line. Never do that. Remove the question mark, add a do - catch block and print the error instance. Decoding errors are extremely descriptive. Commented Nov 15, 2019 at 10:20
  • @jmsiox it's nothing to do with the size of the json, it's to do with the structure of it aligning with your data structures. In your case, it doesn't. If this is your first time working with Codable I'd suggest working through some of the many good tutorials that are out there to get up to speed. Commented Nov 15, 2019 at 10:28

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks alot @vadian this is exactly what I was looking for. I am now able to access the nested Array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.