Swift tip : Perfect Mapper

2018 @ https://www.google.com/maps/dir//54.353655,18.645515

Intro

Often we need to do a raw copy of similar entities (value types) while passing data between our app layers.

A common example is converting a network (received) value…

struct EmployeeDto: Codable {
let id, employeeName, employeeSalary, employeeAge: String?
let profileImage: String?
enum CodingKeys: String, CodingKey {
case id
case employeeName = "employee_name"
case employeeSalary = "employee_salary"
case employeeAge = "employee_age"
case profileImage = "profile_image"
}

into a Model:

struct EmployeeModel {
let id, employeeName, employeeSalary
}

Usually we end up doing a map like this:

extension EmployeeDto {
var toModel: EmployeeModel {
EmployeeModel(id: self.id, employeeName: self.employeeName)
}
}

This is pretty easy/fast/clean, when we have just a couple of properties….

I — Perfect Mapper

So how can we simplify a possibly verbose use case copy like the one below…

extension EmployeeDto {
var toModel: EmployeeModel {
EmployeeModel(id: self.id,
employeeParam1: self.employeeParam2,
employeeParam2: self.employeeParam3,
employeeParam3: self.employeeParam4,
employeeParam4: self.employeeParam5,
employeeParam5: self.employeeParam6,
employeeParam6: self.employeeParam7,
employeeParam7: self.employeeParam8,
employeeParam8: self.employeeParam9,
employeeParam9: self.employeeParam10)

}
}

…into something cleaner as :

extension EmployeeDto {
var toModel: EmployeeModel {
return perfectMapper(inValue: self,
outValue: EmployeeModel.self)

}
}

My tip is to create a function, that receives an (source) Encodable value and a Decodable (target) Type. Then we can use JSONEncoder and JSONDecoder to do the copy for us.

The trick here is (on Line 3) turn inValue (EmployeeDto) into data using JSONEncoder, and then (on Line 4) use JSONDecoder to turn the data into the outValue type (EmployeeModel).

This is possible when the outValue Type have the same (or less) CodingKeys as the inValue value type.

But if we take a look at our Model, it’s not Decodable:

struct EmployeeModel {
let id, employeeName, employeeSalary
}

Well, now it is:

struct EmployeeModel: Decodable {
let id, employeeName: String?
enum CodingKeys: String, CodingKey {
case id
case employeeName = "employee_name"
}

}

At the price of conforming our Model with the Decodable protocol, having the same (or less) CodingKeys asEmployeeDto, we win a free mapping (no matter our big the Dto object is).

Now we can do a quick copy of EmployeeDto into EmployeeModel with one clean and simple line.

extension EmployeeDto {
var toModel: EmployeeModel {
return perfectMapper(inValue: self,
outValue: EmployeeModel.self)

}
}

II — Final notes

The good

  • You save a ton of time using perfect mapper instead of doing a verbose copy between all your Dto’s and Model’s. This is even more noticeable if you are implementing a big API and you don’t have much time.

The bad

  • Perfect mapper copy is not as fast as the verbose (manual) copy (you wont notice unless you are handling thousands of objects at the same time)
  • Your Models will need to comply with Encodable protocol.

III — Materials

--

--

--

https://github.com/ricardopsantos/ricardopsantos

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Level Up your CQRS implementation with MediatR

Leetcode 692. Top K Frequent Words

Developing an Amsterdam Blog with Gatsby, Netlify and Jet Lag

Sec Conference 2019

Leetcode — Insert Delete GetRandom O(1)

Show an image from the network?

Co-Founder AMA (08.28) Recap

Configure Xdebug for VSCode using Docker

PHP Debug extension image

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ricardo Santos

Ricardo Santos

https://github.com/ricardopsantos/ricardopsantos

More from Medium

Swift questions and answers part -III

Best way to use Font Name using enum in iOS-Swift

Dynamic Table View Cell!

Bubble Sort in Swift