{"id":13607707,"url":"https://github.com/YanneckReiss/KConMapper","last_synced_at":"2025-04-12T14:30:57.710Z","repository":{"id":65468621,"uuid":"558120168","full_name":"YanneckReiss/KConMapper","owner":"YanneckReiss","description":"The Kotlin Constructor Mapper (KConMapper / KCM) automatically generates mapping functions for performing mapping between one class and the constructor of another class via the Kotlin Symbol Processing (KSP) compiler plugin.","archived":false,"fork":false,"pushed_at":"2023-11-01T11:52:08.000Z","size":180,"stargazers_count":69,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-07T13:37:14.092Z","etag":null,"topics":["android","data-mapper","java","kotlin","kotlin-library","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YanneckReiss.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-10-26T23:48:11.000Z","updated_at":"2024-09-05T07:45:59.000Z","dependencies_parsed_at":"2023-02-14T11:31:46.658Z","dependency_job_id":"be7aeb22-c8b7-4fd0-911c-c7fcf509cf81","html_url":"https://github.com/YanneckReiss/KConMapper","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YanneckReiss%2FKConMapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YanneckReiss%2FKConMapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YanneckReiss%2FKConMapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YanneckReiss%2FKConMapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YanneckReiss","download_url":"https://codeload.github.com/YanneckReiss/KConMapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248581048,"owners_count":21128094,"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":["android","data-mapper","java","kotlin","kotlin-library","spring-boot"],"created_at":"2024-08-01T19:01:20.907Z","updated_at":"2025-04-12T14:30:57.352Z","avatar_url":"https://github.com/YanneckReiss.png","language":"Kotlin","funding_links":[],"categories":["Kotlin","Bean映射\u0026复制"],"sub_categories":["语音合成"],"readme":"[![Version](https://img.shields.io/github/v/release/yanneckreiss/kconmapper?include_prereleases\u0026style=for-the-badge\u0026color=green)](https://github.com/YanneckReiss/KConMapper/releases)\n[![License Apache 2.0](https://img.shields.io/github/license/yanneckreiss/kconmapper.svg?style=for-the-badge\u0026color=orange)](https://opensource.org/licenses/Apache-2.0)\n[![kotlin](https://img.shields.io/github/languages/top/yanneckreiss/kconmapper?style=for-the-badge\u0026color=blueviolet)](https://kotlinlang.org/)\n\n\u003cp align=\"center\"\u003e \n   \u003cimg height=\"200\" src=\"https://user-images.githubusercontent.com/100080106/208970921-5bc67978-a04e-40a0-8fb9-cafaa2b1334e.png\"/\u003e \n\u003c/p\u003e\n\n\n# KConMapper (KCM)\n\nThe **Kotlin Constructor Mapper (KConMapper / KCM)** is a **Kotlin Symbol Processing (KSP)** plugin that can automatically\ngenerate extension functions to map variables of one class to the primary constructor of another class.\n\n---\n\n## How To Use The Plugin\n\nLet's say you have a class `ExampleEntity`. A common use case is to have various **Data Transfer Object (DTO)** classes\nthat we want to convert into such an `ExampleEntity` class.\n\nit is common for many of the DTO parameters to be the same as those in the corresponding entity class.\nAs a result, we often find ourselves having to manually map the DTO to the target class, which can be a tedious and redundant task.\n\n### Here comes the **KConMapper** into play.\u003c/h2\u003e\n\nOur entity might look like the following:\n\n```kt\nimport java.time.ZonedDateTime\nimport java.util.*\n\ndata class ExampleEntity(\n    val uid: UUID = UUID.randomUUID(),\n    val name: String,\n    val timestamp: ZonedDateTime\n)\n```\n\nNow we want to have a DTO for the CRUD operations of update and create.\n\nThe **create** case might look like the following:\n\n```kt\nimport java.time.ZonedDateTime\n\ndata class CreateExampleDTO(\n    val name: String,\n    val timestamp: ZonedDateTime\n)\n```\n\nWhile the **create** case lacks the `UUID` because it's not created yet, the\n**update** case will contain it:\n\n```kt\nimport java.time.ZonedDateTime\n\ndata class UpdateExampleDTO(\n    val uid: UUID,\n    val name: String,\n    val timestamp: ZonedDateTime\n)\n```\n\nTo create mapping functions, you simply need to add the `@KConMapper` annotation above the target class.\n\n- The **target class**, `ExampleEntity`, is the class whose constructor serves as the schema for the mapping function.\n- The **source classes**, `CreateExampleDTO` and `UpdateExampleDTO`, are the classes whose parameters we want to map to the constructor schema of the target class.\n\n```kt\nimport java.time.ZonedDateTime\nimport java.util.*\n\n@KConMapper(fromClasses = [CreateExampleDTO::class, UpdateExampleDTO::class])\ndata class ExampleEntity(\n    val uid: UUID = UUID.randomUUID(),\n    val name: String,\n    val timestamp: ZonedDateTime\n)\n```\n\nBy executing the `kspKotlin` task, the respective mapping functions get automatically generated as extension functions\nof the\nsource classes.\n\nWith these mapping functions, we can implement the following:\n\n```kt\n    // For the create case:\n    val createExampleDTO = CreateExampleDTO()\n    val exampleEntity: ExampleEntity = createExampleDTO.toExampleEntity()\n    \n    // And for the update case:\n    val updateExampleDTO = UpdateExampleDTO()\n    val exampleEntity: ExampleEntity = updateExampleDTO.toExampleEntity()\n```\n\nIf we want to generate mapping functions from the annotated class to another target class, we can supply the `toClasses` argument:\n\n```kt\nimport java.time.ZonedDateTime\nimport java.util.*\n\n@KConMapper(toClasses = [CreateExampleDTO::class, UpdateExampleDTO::class])\ndata class ExampleEntity(\n    val uid: UUID = UUID.randomUUID(),\n    val name: String,\n    val timestamp: ZonedDateTime\n)\n```\n\nThe code snippet from above would generate the following:\n```kt\n    val exampleEntity: ExampleEntity = ExampleEntity()\n    \n    // For the create case:\n    val createExampleDTO: CreateExampleDTO = exampleEntity.toCreateExampleDTO()\n    \n    // And for the update case:\n    val updateExampleDTO: UpdateExampleDTO = exampleEntity.toUpdateExampleDTO()\n```\n\n## Property name overriding\n\nThe **KConMapper** mapping function works by matching the names of the variables in the source class\nto the ones in the target class. If the names of the variables in the source class do not match\nthe names in the target class, you can use the `@KConMapperProperty` annotation to specify which\nvariables in the source class should be mapped to which variables in the target class.\n\nFor example:\n\n```kotlin\n@KConMapper(fromClasses = [CreateExampleDTO::class])\ndata class ExampleEntity(val name: String, val age: Int)\n\ndata class CreateExampleDTO(val fullName: String, val yearsOld: Int)\n```\nIn this example, the fullName variable in the `CreateExampleDTO` class does\nnot have a matching variable in the `ExampleEntity` class.\nTo map the `fullName` variable to the `name` variable in the `ExampleEntity` class,\nwe would use the `@KConMapperProperty` annotation like this:\n\n```kotlin\n@KConMapper(fromClasses = [CreateExampleDTO::class])\ndata class ExampleEntity(val name: String, val age: Int)\n\ndata class CreateExampleDTO(\n    @KConMapperProperty(\"name\") val fullName: String,\n    @KConMapperProperty(\"age\") val yearsOld: Int\n)\n```\n\nWith the `@KConMapperProperty` annotation in place, the `exampleMapper` function will map the fullName variable in the CreateExampleDTO class to the name variable in the ExampleEntity class and the yearsOld variable to the age variable when it is called.\n\n---\n## Configurations\n\nYou can adapt the configuration of KConMapper to your needs.\n\nTo suppress outputted warnings about missing variable mappings, you can add the following to your `build.gradle` file:\n\n```kotlin\nksp {\n    arg(\"kconmapper.suppressMappingMismatchWarnings\", \"true\")\n}\n```\n\n---\n\n## Setup\nThe following section describes the required setup to use the **KConMapper** KSP plugin in your project.\n\n#### 1. Add the KSP (Kotlin Symbol Processing) plugin:\n\n\u003e Lookup the matching KSP version from the [official GitHub release page](\"https://github.com/google/ksp/releases\")\nof the KSP repository.\nAs an example: If you're using Kotlin version `1.9.20`, the latest KSP would be `1.9.20-1.0.13`.\n\n\u003cdetails open\u003e\n  \u003csummary\u003egroovy - build.gradle(:module-name)\u003c/summary\u003e\n\n```groovy\nplugins {\n    // Depends on your project's Kotlin version\n    id 'com.google.devtools.ksp' version '1.9.20-1.0.13'\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ekotlin - build.gradle.kts(:module-name)\u003c/summary\u003e  \n\n```kt\nplugins {\n    // Depends on your project's Kotlin version\n    id(\"com.google.devtools.ksp\") version \"1.9.20-1.0.13\"\n}\n```\n\u003c/details\u003e\n\n#### 2. Dependency\nAdd the **KConMapper** plugin dependency:\n\n\u003cdetails open\u003e\n  \u003csummary\u003egroovy - build.gradle(:module-name)\u003c/summary\u003e\n\n```groovy\nrepositories {\n    maven { url = 'https://jitpack.io' }    \n}\n\ndependencies {\n    // ..\n    implementation 'com.github.yanneckreiss.kconmapper:annotations:1.0.0-alpha08'\n    ksp 'com.github.yanneckreiss.kconmapper:ksp:1.0.0-alpha08'\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ekotlin - build.gradle.kts(:module-name)\u003c/summary\u003e  \n\n```kt\nrepositories {\n    maven { url = uri(\"https://jitpack.io\") }    \n}\n\ndependencies {\n // ..\n implementation(\"com.github.yanneckreiss.kconmapper:annotations:1.0.0-alpha08\")\n ksp(\"com.github.yanneckreiss.kconmapper:ksp:1.0.0-alpha08\")\n}\n```\n\u003c/details\u003e\n\n#### 3. Add source sets\nTo be able to access the generated classes in your project, you need to add them to your\n`sourceSets`:\n\u003cdetails\u003e\n    \u003csummary\u003eAndroid project\u003c/summary\u003e\n\n```kt\nandroid {\n    sourceSets.configureEach {\n        kotlin.srcDir(\"$buildDir/generated/ksp/$name/kotlin/\")\n    }\n}\n ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eKotlin JVM or equal project\u003c/summary\u003e\n\n```kt\nkotlin.sourceSets {\n    getByName(name) {\n        kotlin.srcDir(\"$buildDir/generated/ksp/$name/kotlin\")\n    }\n}\n ```\n\u003c/details\u003e\n\n---\n\nLicense\n=======\n    Copyright 2022 Yanneck Reiß\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYanneckReiss%2FKConMapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FYanneckReiss%2FKConMapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYanneckReiss%2FKConMapper/lists"}