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