Parse Codable classes and avoid repetition

swift codable dictionary
swift decode array of objects
swift codable example
generic codable swift
swift codable any type
swift decode json
swift unit test decodable
swift decode json file

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.

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?

Taking Advantage of Generics and Codable in Swift, Generics and Codable are two of the greatest features that we get with //Do something because the parsing failed To help make it more clear, lets make our JSON decoder class. This is just a brief example of what you can do with generics and codable. it is always good to avoid code repetition and to  What I want to do is move to a class that conforms to Codable so I can just use JSONDecoder. To do this, I need to structure my classes to look the same as the JSON that NewsApi.org returns. It returns a JSON with a status and an optional list of articles.

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 structs 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

Parsing and working with Codable in Swift 4, JSON parsing requires encoding / decoding tools of this format, and Apple has By default, the Codable protocol supports the following data types: String, In this way, the additional definition of enumeration can often be avoided. You need to spend at least a couple of days on reflection and repetition. Swift 4 brought a lot of cool things like the Codable protocol. It made parsing JSON easier and painless. But some things that were simple with the previous API are not so trivial with the new…

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"  
}

Swift Codable Testing · paul-samuels.com, What do you test when it comes to Swift's Codable? the key name then I would end up with a parsed Swift type that reflects these values. I've used private let outside the scope of the unit test class instead of in an extension in an effort to avoid this I'd rather spend a little bit of time making things clean. Conclusion. Using Swift 4 and Codable protocol, it became very easy to parse any JSON with any complexity and use them in the iOS apps. Thanks to the Foundation framework team to provide such a

How to parse JSON into NSManagedObject with Codable? [duplicate], You can use the Codable interface with CoreData objects to encode and in this class. class MyManagedObject: NSManagedObject, Codable { #NSManaged var Is there a way to avoid this wrapper pattern or a more correct/elegant way of  parse(json: data) This new parse() method does a few new and interesting things: It creates an instance of JSONDecoder, which is dedicated to converting between JSON and Codable objects. It then calls the decode() method on that decoder, asking it to convert our json data into a Petitions object.

Use Codable to parse an array of JSON objects but skip broken , Is there a way to avoid this wrapper pattern or a more correct/elegant way of handling Of course, you can always implement your own custom decoding/​encoding — but How to parse JSON into NSManagedObject with Codable? [​duplicate]. Swift Codable Example: Fetching and Parsing JSON June 5, 2018 by Belal Khan 2 Comments JSON, which is the abbreviation of JavaScript Object Notation, is the most popular data transfer format for app developers.

Swift 4.2 Decodable: Heterogeneous collections 📚 - Kewin , Following last year's release of the Codable protocol, many This is particularly useful to prevent code duplication if several classes would  This is just a brief example of what you can do with generics and codable. it is always good to avoid code repetition and to improve the readability of your code by making what it does, more obvious. If you want to learn more about what you can do with generics I recommend reading this post by James Rochabrun .