{"id":16647764,"url":"https://github.com/liodali/kotlinmapster","last_synced_at":"2026-05-20T21:03:09.754Z","repository":{"id":47715107,"uuid":"327451398","full_name":"liodali/KotlinMapster","owner":"liodali","description":"Fun \u0026 easily way to  map from object to another (inspired from maspter c#)","archived":false,"fork":false,"pushed_at":"2024-03-06T11:39:36.000Z","size":121,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-19T02:44:30.740Z","etag":null,"topics":["kotlin","kotlin-library","kotlin-mapper","mapper","mapping-tools"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/liodali.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-06T23:18:31.000Z","updated_at":"2023-06-10T05:49:21.000Z","dependencies_parsed_at":"2024-11-18T01:40:34.448Z","dependency_job_id":"a20ce97c-ccea-4fbc-8358-816a8a0973cd","html_url":"https://github.com/liodali/KotlinMapster","commit_stats":{"total_commits":149,"total_committers":1,"mean_commits":149.0,"dds":0.0,"last_synced_commit":"000893efe14294268284f82abd7c26fe095551dc"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liodali%2FKotlinMapster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liodali%2FKotlinMapster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liodali%2FKotlinMapster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liodali%2FKotlinMapster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liodali","download_url":"https://codeload.github.com/liodali/KotlinMapster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243204334,"owners_count":20253414,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kotlin","kotlin-library","kotlin-mapper","mapper","mapping-tools"],"created_at":"2024-10-12T08:45:43.842Z","updated_at":"2025-12-25T22:03:45.643Z","avatar_url":"https://github.com/liodali.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Mapster Kotlin \u003cp style=\"font-size:18px\"\u003e(Experimental)\u003c/p\u003e\n\n* Fun and easily mapper from object to another\n* Runtime mapping\n* Nested mapping\n* Array \u0026 List mapping\n* inverse mapping\n\n`stable-version : 0.4.0`\n\n### Gradle Installation\n\n```groovy\n  repositories {\n    // using github packages\n    maven {\n        url = \"https://maven.pkg.github.com/liodali/KotlinMapster\"\n        credentials {\n            username = \"YOUR-USERNAME\"\n            password = \"YOUR-TOKEN-GITHUB\"\n        }\n    }\n}\ndependencies {\n    implementations \"com.dali.hamza:mapster-ktx:version\"\n}\n```\n\n### simple example :\n\n```kotlin\n  data class Person(val email: String, val password: String, val firstName: String)\n  data class PersonDTO(val email: String, val firstName: String)\n  \n  val person = Person(\"lorem@email.com\", \"person\", \"person\",)\n  \n  val dto = person.adaptTo(PersonDTO::class)\n```\n\n### mapping list example :\n\n```kotlin\n\ndata class Person(val email: String, val password: String, val firstName: String)\ndata class PersonDTO(val email: String, val firstName: String)\n\nval persons = listOf(Person(\"lorem@email.com\", \"person\", \"person\",), Person(\"lorem@email.com\", \"person\", \"person\",))\n\nval dtos = persons.adaptListTo(PersonDTO::class)\n```\n\n### Basic Annotation :\n\n* use `MapTo` annotation to map from an attribute to another with difference name\n\n```kotlin\n\ndata class Person(@MapTo(\"login\") val email: String, val password: String, val firstName: String, val adr: Address)\n\ndata class LoginUser(val login: String, val password: String)\n\nval login = person.adaptTo(LoginUser::class)\n\n\n```\n\n### Properties `MapTo`\n\nAttribute     | description | \n--------------| ------------|\n`destAttName` | (String) name of attribute destination         | \n\n\u003cbr\u003e\n\n-------------------------\n\u003cbr\u003e\n\n* use `CombineTo` annotation to combine attributes to another with difference name\n\n```kotlin\n  data class User(\n    @CombineTo(destAtt = \"fullName\", index = 0) val firstName: String,\n    @CombineTo(destAtt = \"fullName\", index = 1) val lastName: String,\n    val CIN: String\n)\n\ndata class UserDTO(\n    val fullName: String,\n    val CIN: String\n)\n\nval dto = user.adaptTo(UserDTO::class)\n\n```\n\n### Properties `CombineTo`\n\n-------------------------\n\nAttribute     | description | \n--------------| ------------|\n`destAtt`     | (String) name of attribute destination         | \n`separator`   | (String) separator between the combined values       | \n`index`       | (Int)  position in final result       | \n\n### Advanced Examples\n\n* `BaseMapper` : mapper instance\n    * you can use `IMapper` interface to pass it into a DI\n    * support list mapping\n    * support nested list mapping and nested Transformation\n  \n\n```kotlin\n\ndata class User(val name: String, val password: String, val country: String, val phone: String)\ndata class UserDTO(val name: String, val password: String)\n\nval faker = Faker() // faker object to generate random data\nval user = User(\n    name = faker.name.firstName(),\n    password = \"1234\",\n    country = faker.address.country(),\n    phone = faker.phoneNumber.phoneNumber()\n)\n\nval mapper = BaseMapper.from(user).to(UserDTO::class)\nval dto = mapper.adapt()\n```\n\n### Map List of object\n\n```kotlin\n\ndata class User(val name: String, val password: String)\ndata class UserDTO(val name: String?, val password: String?)\n\nval users = emptyList\u003cUser\u003e().toMutableList()\nfor (i in 0..2) {\n    val name = faker.name.firstName()\n    val pwd = \"1234\"\n    users.add(User(name, password = pwd))\n}\n// new way to create instance of BaseMapper\nval mapper = BaseMapper\u003cUser, UserDTO\u003e()\n    .to(UserDTO::class).ignore(\"password\")\n\nval dtoList = mapper.adaptList(users)\n```\n\n### Inverse Mapping List \n\n```kotlin\n data class User(val name: String, val password: String)\n data class UserDTO(val name: String, val password: String)\n\n val mapper = BaseMapper\u003cUser, UserDTO\u003e()\n    .from(User::class)\n    .to(UserDTO::class)\n  (1..3).forEach { _ -\u003e\n  \n    val name = faker.name.firstName()\n    val pwd = \"1234\"\n    listDTOs.add(UserDTO(name, password = pwd))\n  }\n /// adaptListInverse for backward mapping from dto to initial object\n val listUser = mapper.adaptListInverse(listDTOs)\n```\n\n## Mapper Manipulation\n\n* you can create custom configuration for `BaseMapper` to manipulate data during mapping\n\n```kotlin\n\n data class User(val name: String, val password: String, val dateCreation: String, val age: Int)\n data class UserDTO(val name: String?, val password: String?, val dateCreation: String?, val age: Int?)\n\n val name = faker.name.firstName()\n val user = User(name, password = \"1234\", \"12/12/2020\", 20)\n\n /// ConfigMapper Instance\n val configMapper = ConfigMapper\u003cUser, UserDTO\u003e()\n    .ignoreAtt(\"age\") // ignore field\n    .ignoreIf(\"dateCreation\") {     // conditional ignore\n        it.dateCreation.isEmpty()  //\n    }\n    .transformation(\"password\") { user -\u003e //transformation\n        hashPassword(user.password)\n    }.map(\"name\", \"login\") // map field to another destination field\n /// BaseMapper Instance\n val mapper = BaseMapper.from(user).to(UserDTO::class).newConfig(configMapper)\n /// map user to dto\n val dto = mapper.adapt()\n```\n### MultiMapping from multiple fields to single field\n* should be used with transformation or InverseTransformation except that is unnecessary to use it\n```kotlin\n data class User(val firstName: String, val lastName: String, val password: String)\n data class UserDTO(val fullName: String, val password: String)\n val mapper = BaseMapper.from(user)\n  .to(UserDTO::class)\n  .transformation(\n    \"fullName\"\n  ) { user -\u003e\n    user.firstName + \" \" + user.lastName\n  }\n  .mapMultiple(arrayOf(\"firstName\", \"lastName\"), \"fullName\")\n\nval dto = mapper.adapt()\n\n```\n### Inverse Mapping\n\n```kotlin\n\ndata class User(val firstName: String, val lastName: String, val password: String)\ndata class UserDTO(val fullName: String, val password: String)\n\nval name = faker.name.firstName()\nval lastName = faker.name.lastName()\nval pwd = \"1234\"\nval user = User(name, lastName, password = pwd)\n\nval mapper = BaseMapper.from(user)\n    .to(UserDTO::class).transformation(\n        \"fullName\"\n    ) { user -\u003e\n        user.firstName + \" \" + user.lastName\n    }.inverseTransformation(\n        \"firstName\"\n    ) { dto -\u003e\n        dto.fullName.split(\" \").first()\n    }.inverseTransformation(\n        \"lastName\"\n    ) { dto -\u003e\n        dto.fullName.split(\" \").last()\n    }.mapMultiple(arrayOf(\"firstName\", \"lastName\"), \"fullName\")\n\nval dto = mapper.adapt()\n// reverse mapping from dto to real object\nval realObject = mapper.adaptInverse(dto)\n```\n\n* you can apply the same manipulation use `BaseMapper` without need to create new `ConfigurationMapper`\n\n### Ignore\n\n    To ignore Field, you need to mark it nullable\n\n* Ignore Field :\n\n```kotlin\n\n data class User(val name: String, val password: String)\n data class UserDTO(val name: String?, val password: String?)\n\n val name = faker.name.firstName()\n val user = User(name, password = \"1234\")\n val mapper = BaseMapper.from(user).to(UserDTO::class)\n    .ignore(\"password\")\n val dto = mapper.adapt()\n```\n\n* Conditional Ignore Field :\n\n  \u003e 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.\n\n  \u003e You can combine it with map to skip field that has different name in destination object.\n\n```kotlin\n\ndata class User(val name: String, val password: String)\ndata class UserDTO(val name: String?, val password: String?)\n\nval name = faker.name.firstName()\n\nval user = User(name, password = \"1234\")\nval mapper = BaseMapper.from(user).to(UserDTO::class)\n    .ignore(\"password\")\nval dto = mapper.adapt()\n  ```\n\n### Transformation :\n\n\u003e you can compute new values using transformation,example hash the password entered by the user\n\n```kotlin\n\ndata class User(val name: String, val email: String, val password: String, val country: String)\ndata class LoginDTO(val login: String?, val password: String?)\n// data preparation\nval name = faker.name.firstName()\nval email = faker.internet.email()\nval country = faker.address.country()\nval user = User(name, email, \"1234\", country)\n\n//BaseMapper builder with mapTo and transformation \nval mapper = BaseMapper.from(user).to(LoginDTO::class)\n    .mapTo(\"email\", \"login\")\n    .transformation(\"password\") { user -\u003e\n        hashPassword(user.password)\n    }\nval dto = mapper.adapt()\n```\n\n### Inverse Transformation :\n\n\u003e you can reverse  value computed using  transformation,example reverse concat of firstName and lastName entered by the user\n\n```kotlin\n\ndata class User(val firstName: String, val lastName: String, val password: String)\ndata class UserDTO(val fullName: String, val password: String)\n\nval name = faker.name.firstName()\nval lastName = faker.name.lastName()\nval pwd = \"1234\"\nval user = User(name, lastName, password = pwd)\n\n//BaseMapper builder with mapTo and transformation \nval mapper = BaseMapper.from(user).to(LoginDTO::class)\n    .mapTo(\"email\", \"login\")\n    .transformation(\n        \"fullName\"\n    ) { user -\u003e\n        user.firstName + \" \" + user.lastName\n    }.inverseTransformation(\n        \"firstName\"\n    ) { dto -\u003e\n        dto.fullName.split(\" \").first()\n    }.inverseTransformation(\n        \"lastName\"\n    ) { dto -\u003e\n        dto.fullName.split(\" \").last()\n    }\n```\n\n### MapTo\n\n\u003e you can map field with difference names using `MapTo`\n\n```kotlin\n\ndata class User(val name: String, val email: String, val password: String, val country: String)\ndata class LoginDTO(val login: String?, val password: String?)\n\nval user = User(faker.name.firstName(), faker.internet.email(), password = \"1234\", faker.address.country())\n\nval mapper = BaseMapper.from(user).to(UserDTO::class)\n    .mapTo(\"email\", \"login\")\nval dto = mapper.adapt()\n```\n\n### MapMultiple\n\n\u003e you can  map multiple fields to single destination field  using `mapMultiple`\n\u003e the best usage is  with InverseTransformation (see example above)\n\n```kotlin\n\ndata class User(val firstName: String, val lastName: String, val password: String)\ndata class UserDTO(val fullName: String, val password: String)\n\nval name = faker.name.firstName()\nval lastName = faker.name.lastName()\nval pwd = \"1234\"\nval user = User(name, lastName, password = pwd)\n\nval mapper = BaseMapper.from(user).to(UserDTO::class)\n    .mapMultiple(arrayOf(\"firstName\", \"lastName\"), \"fullName\")\nval dto = mapper.adapt()\n```\n\n### PS\n\n* To create Github personal token follow this link and also you need to choose `read:packages` :\n    * https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliodali%2Fkotlinmapster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliodali%2Fkotlinmapster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliodali%2Fkotlinmapster/lists"}