Home > database >  Unable to decode JSON data while parsing in swift
Unable to decode JSON data while parsing in swift

Time:07-24

I am using generic codable protocol for JSON parsing

below is the JSON structure and postman response

 {
"jsonrpc": "2.0",
"result": {
    "categories": [
        {
            "id": 91,
            "title": "ADMINISTRATION & SECRETARIAL",
        },
        {
            "id": 62,
            "title": "BEAUTY",
        },
        {
            "id": 325,
            "title": "CARE",
           

for above response i have created model like below:

struct CategoryModel: Codable {

    let jsonrpc: String?
    let result: ResultCat?
}

struct ResultCat: Codable {
    let categories: [Categorymine]?
}

struct Categorymine: Codable {
    let id: Int?
    let title, slug: String?
}

code: in this code i am getting response above switch response.result case and data also getting (11113 bytes).. but here i am unable to decode data i think.. when i call service not getting response

please guide me to get response

first time i am working with generics, where am i wrong. please guide me

import Foundation
import Alamofire

class GeneralResponse<T: Codable>: Codable {
var jsonrpc: String
var result: T?
}

struct RequestObject {
var method: HTTPMethod
var path: String
var token: String?
var params: [String: Any]?
}


class WebService {

private let decoder: JSONDecoder

public init(_ decoder: JSONDecoder = JSONDecoder()) {
    self.decoder = decoder
}

public func serviceCall<T: Codable>(_ objectType: T.Type,
                                    with request: RequestObject,
                                    completion: @escaping  (GeneralResponse<T>?, Error?) -> Void)  {
    
    
    var headerParams: HTTPHeaders?
    AF.request(request.path, method: request.method, parameters: request.params,encoding: JSONEncoding.default, headers: headerParams)
        .responseJSON { response in
            
            print("Json response: \(response)")//getting response here as well
            switch response.result {
            case .success(let dictData):
                let JSON = dictData as? [String : Any]
                
                do {
                    let data = response.data
                    print("only data \(data)")//Optional(11113 bytes)
                    let responseData  = try self.decoder.decode(GeneralResponse<T>.self, from: data ?? Data())
                    print("model data \(String(describing: responseData.result))")//Optional(TestigAllInOne.CategoryModel(jsonrpc: nil, result: nil))
                    
                } catch {
                    completion(nil, error)
                }
            case .failure(let error):
                let error = error
                print(error.localizedDescription)
            }
        }
}
}

in console i am getting like this:

only data Optional(11113 bytes)

model data Optional(TestigAllInOne.CategoryModel(jsonrpc: nil, result: nil))

i am using service call in viewcontroller like this:

var catData: CategoryModel? {
didSet {}
 }


 func genericCall(){

let request = RequestObject(method: .get, path: "https://tt.com/dev/api/get-category", params: nil)
    
WebService().serviceCall(CategoryModel.self, with: request) { (response, error) in
    if let items = response?.result {
        
        print("viewcontroller response \(items)")
        DispatchQueue.main.sync {
            self.catData = items
            self.tableView.reloadData()
        }
    }
    else{
        print(error)
    }
}
}

CodePudding user response:

Acording to your Model T should be of type ResultCat and not CategoryModel

WebService().serviceCall(ResultCat.self, with: request)

look at your generic class:

class GeneralResponse<T: Codable>: Codable {
    var jsonrpc: String
    var result: T?
}

so T in this context is the type of the result var.


Edit to address the comment:

if i want to pass whole CategoryModel in serviceCall then how to change my code.

I asume you want to call the function as described in the question. To achieve this simply get rid of your generic struct as you wouldn´t use it in that case.

public func serviceCall<T: Codable>(_ objectType: T.Type,
                                    with request: RequestObject,
                                    completion: @escaping  (T?, Error?) -> Void)  {

and:

let responseData  = try self.decoder.decode(T.self, from: data ?? Data())
  • Related