Reputation: 8396
I have a JSON response as the following:
{
"http_status": 200,
"success": true,
"has_error": false,
"error": [
""
],
"response": {
"token": "",
"verified": false,
"message": ""
}
}
As far as i can say for an app API usage http_status, success, has_error, error are shared between all APIS and thus i will create a Codable class to handle it, but the response could be different model, so here is what I'm trying to do.
I have created a general response class as the below, so this class i can use for all apis in the project to avoid duplication of same class but different names:
class GeneralResponse:Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
enum CodingKeys: String, CodingKey {
case http_status = "http_status"
case success = "success"
case has_error = "has_error"
case error = "error"
}
init(http_status: Int?, success: Bool?, has_error: Bool?,error: [String]?) {
self.http_status = http_status
self.success = success
self.has_error = has_error
self.error = error
}
}
Now i have created the response class which will handle for now the registration response:
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
init(token: String?, verified: Bool?, message: String?) {
self.token = token
self.verified = verified
self.message = message
}
}
And lets say i need to parse the registration the response so here is what i did, i have created a class and used both of them:
class RegistrationResponse: Codable {
let generalResponse:GeneralResponse?
let response: RegistrationResponseDetails?
init(generalResponse: GeneralResponse?, response: RegistrationResponseDetails?) {
self.generalResponse = generalResponse
self.response = response
}
}
So i will mainly use RegistrationResponse to parse the response which will parse "generalResponse" which includes http_status, success, has_error, error, and then response will parse the desired response object.
But at some point generalResponse object is always nil and response has the data parsed correctly, what should i do to make generalResponse get parsed without duplication in each api, because in each api i will have generalResponse object so is it possible to solve it ?
Note: I'm using Alamofire as the networking library.
Upvotes: 2
Views: 90
Reputation: 100503
For a simple case
class Main:Decodable {
let name:String? // insert all shared vars
}
class Sub:Main {
let id:String?
}
This will parse
{
"name" : "rr" ,
"id" : "oo"
}
Upvotes: 1
Reputation: 285069
First of all if
http_status, success, has_error, error are shared between all APIS
why are the class properties optional?
If the mentioned keys are the same but the value for key response
is different use generics.
In most cases struct
s are sufficient.
struct JSONParser<T : Decodable> {
struct Response<U : Decodable> : Decodable {
let httpStatus: Int
let success, hasError: Bool
let error: [String]
let response : U
}
let responseData : Response<T>
init(data: Data) throws {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
responseData = try decoder.decode(Response.self, from: data)
}
}
Then create the different structs e.g.
struct RegistrationResponseDetails : Decodable {
let token: String
let verified: Bool
let message: String
}
and parse it
let parser = try JSONParser<RegistrationResponseDetails>(data: data)
let registrationResponseDetails = parser.responseData.response
Upvotes: 1
Reputation: 9825
You can make your GeneralResponse
generic and tell it what type to use when parsing the response:
class GeneralResponse<T: Codable>: Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
let response: T?
}
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
}
Then you can give it the inner response class when you parse the json:
let generalResponse = try JSONDecoder().decode(GeneralResponse<RegistrationResponseDetails>.self, from: jsonData)
// generalResponse.response is of type RegistrationResponseDetails?
Upvotes: 1