https://github.com/liodali/kotlinmapster
Fun & easily way to map from object to another (inspired from maspter c#)
https://github.com/liodali/kotlinmapster
kotlin kotlin-library kotlin-mapper mapper mapping-tools
Last synced: about 1 month ago
JSON representation
Fun & easily way to map from object to another (inspired from maspter c#)
- Host: GitHub
- URL: https://github.com/liodali/kotlinmapster
- Owner: liodali
- Created: 2021-01-06T23:18:31.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2024-03-06T11:39:36.000Z (over 2 years ago)
- Last Synced: 2025-01-19T02:44:30.740Z (over 1 year ago)
- Topics: kotlin, kotlin-library, kotlin-mapper, mapper, mapping-tools
- Language: Kotlin
- Homepage:
- Size: 118 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Mapster Kotlin
(Experimental)
* Fun and easily mapper from object to another
* Runtime mapping
* Nested mapping
* Array & List mapping
* inverse mapping
`stable-version : 0.4.0`
### Gradle Installation
```groovy
repositories {
// using github packages
maven {
url = "https://maven.pkg.github.com/liodali/KotlinMapster"
credentials {
username = "YOUR-USERNAME"
password = "YOUR-TOKEN-GITHUB"
}
}
}
dependencies {
implementations "com.dali.hamza:mapster-ktx:version"
}
```
### simple example :
```kotlin
data class Person(val email: String, val password: String, val firstName: String)
data class PersonDTO(val email: String, val firstName: String)
val person = Person("lorem@email.com", "person", "person",)
val dto = person.adaptTo(PersonDTO::class)
```
### mapping list example :
```kotlin
data class Person(val email: String, val password: String, val firstName: String)
data class PersonDTO(val email: String, val firstName: String)
val persons = listOf(Person("lorem@email.com", "person", "person",), Person("lorem@email.com", "person", "person",))
val dtos = persons.adaptListTo(PersonDTO::class)
```
### Basic Annotation :
* use `MapTo` annotation to map from an attribute to another with difference name
```kotlin
data class Person(@MapTo("login") val email: String, val password: String, val firstName: String, val adr: Address)
data class LoginUser(val login: String, val password: String)
val login = person.adaptTo(LoginUser::class)
```
### Properties `MapTo`
Attribute | description |
--------------| ------------|
`destAttName` | (String) name of attribute destination |
-------------------------
* use `CombineTo` annotation to combine attributes to another with difference name
```kotlin
data class User(
@CombineTo(destAtt = "fullName", index = 0) val firstName: String,
@CombineTo(destAtt = "fullName", index = 1) val lastName: String,
val CIN: String
)
data class UserDTO(
val fullName: String,
val CIN: String
)
val dto = user.adaptTo(UserDTO::class)
```
### Properties `CombineTo`
-------------------------
Attribute | description |
--------------| ------------|
`destAtt` | (String) name of attribute destination |
`separator` | (String) separator between the combined values |
`index` | (Int) position in final result |
### Advanced Examples
* `BaseMapper` : mapper instance
* you can use `IMapper` interface to pass it into a DI
* support list mapping
* support nested list mapping and nested Transformation
```kotlin
data class User(val name: String, val password: String, val country: String, val phone: String)
data class UserDTO(val name: String, val password: String)
val faker = Faker() // faker object to generate random data
val user = User(
name = faker.name.firstName(),
password = "1234",
country = faker.address.country(),
phone = faker.phoneNumber.phoneNumber()
)
val mapper = BaseMapper.from(user).to(UserDTO::class)
val dto = mapper.adapt()
```
### Map List of object
```kotlin
data class User(val name: String, val password: String)
data class UserDTO(val name: String?, val password: String?)
val users = emptyList().toMutableList()
for (i in 0..2) {
val name = faker.name.firstName()
val pwd = "1234"
users.add(User(name, password = pwd))
}
// new way to create instance of BaseMapper
val mapper = BaseMapper()
.to(UserDTO::class).ignore("password")
val dtoList = mapper.adaptList(users)
```
### Inverse Mapping List
```kotlin
data class User(val name: String, val password: String)
data class UserDTO(val name: String, val password: String)
val mapper = BaseMapper()
.from(User::class)
.to(UserDTO::class)
(1..3).forEach { _ ->
val name = faker.name.firstName()
val pwd = "1234"
listDTOs.add(UserDTO(name, password = pwd))
}
/// adaptListInverse for backward mapping from dto to initial object
val listUser = mapper.adaptListInverse(listDTOs)
```
## Mapper Manipulation
* you can create custom configuration for `BaseMapper` to manipulate data during mapping
```kotlin
data class User(val name: String, val password: String, val dateCreation: String, val age: Int)
data class UserDTO(val name: String?, val password: String?, val dateCreation: String?, val age: Int?)
val name = faker.name.firstName()
val user = User(name, password = "1234", "12/12/2020", 20)
/// ConfigMapper Instance
val configMapper = ConfigMapper()
.ignoreAtt("age") // ignore field
.ignoreIf("dateCreation") { // conditional ignore
it.dateCreation.isEmpty() //
}
.transformation("password") { user -> //transformation
hashPassword(user.password)
}.map("name", "login") // map field to another destination field
/// BaseMapper Instance
val mapper = BaseMapper.from(user).to(UserDTO::class).newConfig(configMapper)
/// map user to dto
val dto = mapper.adapt()
```
### MultiMapping from multiple fields to single field
* should be used with transformation or InverseTransformation except that is unnecessary to use it
```kotlin
data class User(val firstName: String, val lastName: String, val password: String)
data class UserDTO(val fullName: String, val password: String)
val mapper = BaseMapper.from(user)
.to(UserDTO::class)
.transformation(
"fullName"
) { user ->
user.firstName + " " + user.lastName
}
.mapMultiple(arrayOf("firstName", "lastName"), "fullName")
val dto = mapper.adapt()
```
### Inverse Mapping
```kotlin
data class User(val firstName: String, val lastName: String, val password: String)
data class UserDTO(val fullName: String, val password: String)
val name = faker.name.firstName()
val lastName = faker.name.lastName()
val pwd = "1234"
val user = User(name, lastName, password = pwd)
val mapper = BaseMapper.from(user)
.to(UserDTO::class).transformation(
"fullName"
) { user ->
user.firstName + " " + user.lastName
}.inverseTransformation(
"firstName"
) { dto ->
dto.fullName.split(" ").first()
}.inverseTransformation(
"lastName"
) { dto ->
dto.fullName.split(" ").last()
}.mapMultiple(arrayOf("firstName", "lastName"), "fullName")
val dto = mapper.adapt()
// reverse mapping from dto to real object
val realObject = mapper.adaptInverse(dto)
```
* you can apply the same manipulation use `BaseMapper` without need to create new `ConfigurationMapper`
### Ignore
To ignore Field, you need to mark it nullable
* Ignore Field :
```kotlin
data class User(val name: String, val password: String)
data class UserDTO(val name: String?, val password: String?)
val name = faker.name.firstName()
val user = User(name, password = "1234")
val mapper = BaseMapper.from(user).to(UserDTO::class)
.ignore("password")
val dto = mapper.adapt()
```
* Conditional Ignore Field :
> You can ignore Field Conditionally with condition base on source, when condition is met,the field that has the same name in destination object will be skipped.
> You can combine it with map to skip field that has different name in destination object.
```kotlin
data class User(val name: String, val password: String)
data class UserDTO(val name: String?, val password: String?)
val name = faker.name.firstName()
val user = User(name, password = "1234")
val mapper = BaseMapper.from(user).to(UserDTO::class)
.ignore("password")
val dto = mapper.adapt()
```
### Transformation :
> you can compute new values using transformation,example hash the password entered by the user
```kotlin
data class User(val name: String, val email: String, val password: String, val country: String)
data class LoginDTO(val login: String?, val password: String?)
// data preparation
val name = faker.name.firstName()
val email = faker.internet.email()
val country = faker.address.country()
val user = User(name, email, "1234", country)
//BaseMapper builder with mapTo and transformation
val mapper = BaseMapper.from(user).to(LoginDTO::class)
.mapTo("email", "login")
.transformation("password") { user ->
hashPassword(user.password)
}
val dto = mapper.adapt()
```
### Inverse Transformation :
> you can reverse value computed using transformation,example reverse concat of firstName and lastName entered by the user
```kotlin
data class User(val firstName: String, val lastName: String, val password: String)
data class UserDTO(val fullName: String, val password: String)
val name = faker.name.firstName()
val lastName = faker.name.lastName()
val pwd = "1234"
val user = User(name, lastName, password = pwd)
//BaseMapper builder with mapTo and transformation
val mapper = BaseMapper.from(user).to(LoginDTO::class)
.mapTo("email", "login")
.transformation(
"fullName"
) { user ->
user.firstName + " " + user.lastName
}.inverseTransformation(
"firstName"
) { dto ->
dto.fullName.split(" ").first()
}.inverseTransformation(
"lastName"
) { dto ->
dto.fullName.split(" ").last()
}
```
### MapTo
> you can map field with difference names using `MapTo`
```kotlin
data class User(val name: String, val email: String, val password: String, val country: String)
data class LoginDTO(val login: String?, val password: String?)
val user = User(faker.name.firstName(), faker.internet.email(), password = "1234", faker.address.country())
val mapper = BaseMapper.from(user).to(UserDTO::class)
.mapTo("email", "login")
val dto = mapper.adapt()
```
### MapMultiple
> you can map multiple fields to single destination field using `mapMultiple`
> the best usage is with InverseTransformation (see example above)
```kotlin
data class User(val firstName: String, val lastName: String, val password: String)
data class UserDTO(val fullName: String, val password: String)
val name = faker.name.firstName()
val lastName = faker.name.lastName()
val pwd = "1234"
val user = User(name, lastName, password = pwd)
val mapper = BaseMapper.from(user).to(UserDTO::class)
.mapMultiple(arrayOf("firstName", "lastName"), "fullName")
val dto = mapper.adapt()
```
### PS
* To create Github personal token follow this link and also you need to choose `read:packages` :
* https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token