iosswiftccavenue

not able to parse the JSON using JSON decoder


I am new to swift and i am trying to integrate the CCAvenue payment gateway. I am hitting the server to get the payment option list from the CCAvenue server which i an getting in the response but i am not able to parse the data into a JSON object, it is throwing some exception. Thanks in advance for the help

here is my code

override func viewDidLoad() {
        super.viewDidLoad()

let urlAsString = "https://test.ccavenue.com/transaction/transaction.do?"

        let myRequestString = "command=\(COMMAND)&currency=\(currency)&amount=\(amount)&access_code=\(accessCode)&customer_identifier=\(customerIdentifier)"
        let myRequestData = NSData.init(bytes: myRequestString.cString(using: .utf8), length: myRequestString.count) as Data
        let request = NSMutableURLRequest.init(url: URL(string: urlAsString)!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "content-type")
        request.setValue(urlAsString, forHTTPHeaderField: "Referer")
        request.setValue("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", forHTTPHeaderField: "User-Agent")
        request.httpMethod = "POST"
        request.httpBody = myRequestData

        let requestData = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
            let responseData = NSString.init(data: data!, encoding: String.Encoding.ascii.rawValue)

            if error == nil {
                print("\(responseData)")
            }

            // if request is error free then decode the json using json decoder and assigning the values to the array
            guard let data = data  else {return}
            do{
               let a = try JSONDecoder().decode([CCPaymentOption].self, from: data)

                print("\(String(describing: a))")
            }catch {
                print("Error")
            }
            }.resume()

        print("\(requestData)")
    }

this is what i am getting in my debugger

Optional({"payOptions":[{"payOpt":"OPTCRDC","payOptDesc":"Credit Card","cardsList":"[{\"cardName\":\"Diners Club\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"MasterCard\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"},{\"cardName\":\"Visa\",\"cardType\":\"CRDC\",\"payOptType\":\"OPTCRDC\",\"payOptDesc\":\"Credit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTDBCRD","payOptDesc":"Debit Card","cardsList":"[{\"cardName\":\"MasterCard Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"},{\"cardName\":\"Visa Debit Card\",\"cardType\":\"DBCRD\",\"payOptType\":\"OPTDBCRD\",\"payOptDesc\":\"Debit Card\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\"}]"},{"payOpt":"OPTNBK","payOptDesc":"Net Banking","cardsList":"[{\"cardName\":\"AvenuesTest\",\"cardType\":\"NBK\",\"payOptType\":\"OPTNBK\",\"payOptDesc\":\"Net Banking\",\"dataAcceptedAt\":\"CCAvenue\",\"status\":\"ACTI\",\"statusMessage\":\"\"}]"}]})

Error


Solution

  • There are many points needed to be checked while decoding the object.

    1. Make sure your CCPaymentOption Model addopt the Protocol Codable.
    2. While Decoding the Data , make sure you are aware of thing that your response is in form of Dictionary or Array
    3. lets say you are getting the Array in response , in that case you can directly use [CCPaymentOption] in JSONDecoder().decode() method.
    4. And if you are getting the Dictionary from the server response then you need to decode the object on that way.

    Example of CCPaymentOption Model for point no 3.

    struct CCPaymentOption : Codable {
        var amount:String  // Note down that , please use exact same 
                           // key as you are getting from server side.
    }
    
    do {
    
           let arrPaymentOptions = try JSONDecoder().decode([CCPaymentOption].self, from: responseData)
    
                   print(arrPaymentOptions)
                   ///... Array of Your Model reference.
    
        } catch {
                   print(error)
                }
    

    Example of CCPaymentOption Model for point no 4.

    struct CCPaymentOption : Codable {
        var amount:String
    }
    
    struct responseDictionary : Codable {
        var paymentOption:[CCPaymentOption] // Note down that , please 
                                            // use exact same key as you 
                                            // are getting from server 
                                            // side.
    }
    
    do {
    
            let responseDict = try JSONDecoder().decode(responseDictionary.self, from: responseData)
    
                   print(responseDict.paymentOption)
                   // responseDict.paymentOption is the Array of Your 
                   // Model reference.
    
        } catch {
                   print(error)
                }
    

    Please try out the below one if you don't want to use the JSON decoder. :-

    URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
    
                        guard error == nil else { return }
                        guard let responseData = data else { return }
    
                        do {
    
                            if let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String:Any] {
                                ///... All you want is here  jsonObject is the Dictionary (required , not an optional)  
                            }
    
                        } catch  {
                            print(error)
                        }
                    }).resume()
    

    After getting the data from server side , you need to do JSONSerialization with the help of native method. This method will return the Dictionary or Array (Depending on your server response.)