An open API service indexing awesome lists of open source software.

https://github.com/wickwirew/converter

An automatic convention based, boiler plate free, object mapper for Swift
https://github.com/wickwirew/converter

ios reflection runtime swift

Last synced: about 1 year ago
JSON representation

An automatic convention based, boiler plate free, object mapper for Swift

Awesome Lists containing this project

README

          

![Converter](https://github.com/wickwirew/Converter/blob/master/Resources/Converter.png)

## Converter
Converter is an automatic convention based object mapper similar to [AutoMapper](https://github.com/AutoMapper/AutoMapper) for Swift.

## Why?
There comes time where you have two models, with similar properties, that follow the same naming standard. Whether it's a domain model for your persistance layer, a DTO for an API request, or just a slimmed down version. Mapping the object between types usually results in a lot of boiler plate code manually mapping each property. Converter takes the hassle away and does it automatically base off the naming convention.

## Example
For example we have the `Source` type. We want to be able to convert objects of the `Source` type to `Destination`. So first we have to create the conversion. The conversions are static and only need to be created once, usually when the application is started.
```swift
try createConversion(from: Source.self, to: Destination.self)
```
Once the conversion is created to convert the object:
```swift
let newObject = try convert(mySourceObject, to: Destination.self)
```
It's that easy! No boiler plate code to write 🎉.

## AWS Example
If you use the AWS Mobile Hub when it generates the domain models for the DynamoDb instance every property is prefixed with an underscore, and they are classes by default. Say you would like to use structs instead and not have the underscore you would normally have to write code to convert the AWS domain model to the struct model. Converter will do this automatically!
```swift
class PetDomain: AWSDynamoDBObjectModel, AWSDynamoDBModeling {
var _userId: String?
var _name: String?
var _age: Int
}

struct Pet {
var userId: String?
var name: String?
var age: Int
}

try createConversion(from: PetDomain.self, to: Pet.self)

let pet = try convert(domain, to: Pet.self)
```

## Custom Maps
Say you have two models that are similar but the property names don't match perfectly. Or even one property in the destination type is a combination of two on the source type. For example we have a `Person` type and a `Teacher` type. `Person` has `firstName` and `lastName` while the `Teacher` object only has `name`.
```swift
struct Person {
var id: Int
var firstName: String
var lastName: String
var age: Int
}

struct Teacher {
var id: Int
var name: String
var age: Int
}
```
To specify which property to use for the `Teacher.name` property you can choose from a `KeyPath` on the source type.
```swift
try createConversion(from: Person.self, to: Teacher.self)
.for(property: "name", use: \.firstName)
```
Or for more flexibility you can use a closure to allow you to use multiple properties on the source object.
```swift
try createConversion(from: Person.self, to: Teacher.self)
.for(property: "name", use: {"\($0.firstName) \($0.lastName)"})
```

## Ignoring Properties
Say on one conversion you would like to omit one property from being set. Example:
```swift
try createConversion(from: Person.self, to: Teacher.self)
.ignore(property: "lastName")
```
## Property Matching
Converter tries to be intelligent when matching properties on the source to the destination type. It will automatically handle mapping to and from different casing styles, including `camelCasing`, `PascalCasing`, and `snake_casing`. So for example `SomePropertyName` or `some_property_name` can be instantly mapped to and from `somePropertyName`

Private properties sometimes are noted with an underscore at the beginning. Converter will automatically convert them as well. So for example `firstName` can be mapped automatically to and from `_firstName`.

If you would like the conversion to match properties only when the names are an exact match then when the conversion if created you can specify a `strict` matching policy.

Example:
```swift
try createConversion(from: Person.self, to: Teacher.self, matching: .strict)
```

## Flattening
Converter also has the ability to flatten out objects, allowing you to automatically pull values out of nested objects with no extra work. For example we have the `Person` type which has a property of type `Pet`. `Pet` objects have a name property. Our destination type would like the pet name to be at the top level. `Person`'s pet property name is `pet` and we would like to flatten out it's `name` property. So by naming our destination property `petName`, Converter will translate that too `pet.name` and grab the value.
```swift
struct Pet {
var name: String
}

struct Person {
var pet: Pet
}

struct FlattenedPerson {
var petName: String
}

try createConversion(from: Person.self, to: FlattenedPerson.self)

let source = Person(pet: Pet(name: "Marley"))
let person: Destination = try convert(source)
print(person.petName) // prints Marley
```

## Arrays
Conversions can be made from an array of a source type to an array of a destination type. There is no need to create an extra conversion for an array, just the type within. Example:
```swift
try createConversion(from: Source.self, to: Destination.self)
let new: [Destination] = try convert(arrayOfSourceObjects)
```

## How Does it Work?
To get and set the values dynamically it uses my other library [Runtime](https://github.com/wickwirew/Runtime). Converter will automatically convert two objects when the property names are the same, and allows for custom mappings. The `createConversion(from: to:)` method defines a path of how it will be converted. Some of the more expensive operations are done once when the conversion is created making the conversion just a wee bit faster.

## Contributions
Anyone is welcome to contribute! It is still a work in progress. If there is something you would like implemented either send a pull request or open an issue. Any questions also feel free to open an issue.

## License
Converter is available under the MIT license. See the LICENSE file for more info.