{"id":27154679,"url":"https://github.com/scogun/komm","last_synced_at":"2025-04-08T17:51:06.067Z","repository":{"id":215921747,"uuid":"739757749","full_name":"Scogun/komm","owner":"Scogun","description":"Kotlin Object Multiplatform Mapper","archived":false,"fork":false,"pushed_at":"2024-04-14T08:15:52.000Z","size":228,"stargazers_count":8,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-14T09:51:28.900Z","etag":null,"topics":["kotlin","kotlin-multiplatform","mapper"],"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/Scogun.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,"dei":null}},"created_at":"2024-01-06T13:05:06.000Z","updated_at":"2024-07-27T10:20:15.267Z","dependencies_parsed_at":"2024-01-15T15:54:52.754Z","dependency_job_id":"7a5dfb5f-aba7-4ece-bcf5-46d05d63852e","html_url":"https://github.com/Scogun/komm","commit_stats":null,"previous_names":["scogun/komm"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Scogun%2Fkomm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Scogun%2Fkomm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Scogun%2Fkomm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Scogun%2Fkomm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Scogun","download_url":"https://codeload.github.com/Scogun/komm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247897178,"owners_count":21014685,"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-multiplatform","mapper"],"created_at":"2025-04-08T17:51:05.463Z","updated_at":"2025-04-08T17:51:06.057Z","avatar_url":"https://github.com/Scogun.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kotlin Object Multiplatform Mapper (KOMM)\n\nThe **Kotlin Object Multiplatform Mapper** provides you a possibility to generate (via [KSP](https://github.com/google/ksp)) extension function to map one object to another.\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Scogun_komm\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Scogun_komm)\n[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=Scogun_komm\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=Scogun_komm)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=Scogun_komm\u0026metric=ncloc)](https://sonarcloud.io/summary/new_code?id=Scogun_komm)  \n![GitHub](https://img.shields.io/github/license/Scogun/komm?color=blue)  \n![Publish workflow](https://github.com/Scogun/komm/actions/workflows/publish.yml/badge.svg)\n[![Maven Central](https://img.shields.io/maven-central/v/com.ucasoft.komm/komm-annotations?label=KOMM-Annotations\u0026color=blue)](https://search.maven.org/artifact/com.ucasoft.komm/komm-annotations)\n[![Maven Central](https://img.shields.io/maven-central/v/com.ucasoft.komm/komm-processor?label=KOMM-Processоr\u0026color=blue)](https://search.maven.org/artifact/com.ucasoft.komm/komm-processor)\n[![Maven Central](https://img.shields.io/maven-central/v/com.ucasoft.komm/komm-plugins-iterable?label=KOMM-Plugins-Iterable\u0026color=blue)](https://search.maven.org/artifact/com.ucasoft.komm/komm-plugins-iterable)\n---\n* [Features](#features)\n* [Supported targets](#supported-targets)\n* [Default plugins](#default-plugins)\n* [Usage](#usage)\n  * [Add](#add-with-gradle)\n    * [JVM project](#jvm-project)\n    * [Multiplatform project](#multiplatform-project)\n  * [Simple mapping](#simple-mapping)\n  * [Configuration](#mapping-configuration)\n    * [Disable AutoCast](#disable-autocast)\n    * [Change Convert Function Name](#change-convert-function-name)\n  * [@MapName](#mapname-annotation)\n  * [@MapConverter](#use-converter)\n  * [@MapDefault](#use-resolver)\n  * [@NullSubstitute](#use-nullsubstitute)\n    * [Allow Not-Null Assertion](#mapping-configuration-1)\n  * [Multi Sources](#multi-sources-support)\n* [Plugins](#plugins)\n  * [Iterable Plugin - Collections Mapping](#iterable-plugin---collections-mapping)\n    * [Add](#add-with-gradle-1)\n      * [JVM project](#jvm-project-1)\n      * [Multiplatform project](#multiplatform-project-1)\n    * [Allow NotNullAssertion](#allow-notnullassertion)\n    * [NullSubstitute](#nullsubstitute)\n  * [Exposed Plugin - ResultRow Mapping](#exposed-plugin---resultrow-mapping)\n    * [Add](#add-with-gradle-2)\n    * [Usage](#usage-1)\n---\n\n## Features\n* Supports KSP Multiplatform\n* Maps as constructor parameters as well as public properties with setter\n* Supports properties types cast\n* Supports Java objects get* functions\n* Supports multi source classes with separated configurations\n* Has next properties annotations:\n  * Specify mapping from property with different name\n  * Specify a converter to map data from source unusual way\n  * Specify a resolver to map default values into properties\n  * Specify null substitute to map nullable properties into not-nullable\n* Support extension via plugins\n\n## Supported targets\n* JVM\n* JavaScript\n* Linux\n* Windows (mingwX64)\n* macOS\n* iOS\n\n## Default plugins\n* Iterable Plugin:\n  * Support collections mapping with different types of elements\n* Exposed Plugin:\n  * Support mapping from Exposed Table Object (ResultRow)\n\n## Usage\n### Add with Gradle\n\n#### JVM Project\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.0-1.0.28\"\n}\n\nval kommVersion = \"0.22.8\"\n\ndepensencies {\n    implementation(\"com.ucasoft.komm:komm-annotations:$kommVersion\")\n    ksp(\"com.ucasoft.komm:komm-processor:$kommVersion\")\n}\n```\n#### Multiplatform Project\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.0-1.0.28\"\n}\n\nval kommVersion = \"0.22.8\"\n\nkotlin {\n    jvm {\n        withJava()\n    }\n    js(IR) {\n        nodejs()\n    }\n    // Add other platforms\n    sourceSets {\n        val commonMain by getting {\n            dependencies {\n                implementation(\"com.ucasoft.komm:komm-annotations:$kommVersion\")\n            }\n        }\n        val jvmMain by getting\n        val jsMain by getting\n        // Init other sourceSets\n    }\n}\n\ndependencies {\n    add(\"kspJvm\", \"com.ucasoft.komm:komm-processor:$kommVersion\")\n    add(\"kspJs\", \"com.ucasoft.komm:komm-processor:$kommVersion\")\n    // Add other platforms like `kspAndroidNativeX64`, `kspLinuxX64`, `kspMingwX64` etc.\n}\n```\n\n### Simple Mapping\n#### Classes declaration\n```kotlin\nclass SourceObject {\n\n    val id = 150\n\n    val intToString = 300\n\n    val stringToInt = \"250\"\n}\n\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    val id: Int,\n    val stringToInt: Int\n) {\n    var intToString: String = \"\"\n}\n```\nor\n```kotlin\n@KOMMMap(to = [DestinationObject::class])\nclass SourceObject {\n\n    val id = 150\n\n    val intToString = 300\n\n    val stringToInt = \"250\"\n}\n\ndata class DestinationObject(\n    val id: Int,\n    val stringToInt: Int\n) {\n    var intToString: String = \"\"\n}\n```\n#### Generated extension function\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    id = id,\n    stringToInt = stringToInt.toInt()\n).also { \n    it.intToString = intToString.toString()\n}\n```\n\n### Mapping Configuration\n#### Disable AutoCast\n###### Classes declaration\n```kotlin\n@KOMMMap(\n    from = [SourceObject::class],\n    config = MapConfiguration(\n        tryAutoCast = false\n    )\n)\ndata class DestinationObject(\n    val id: Int,\n    val stringToInt: Int\n) {\n    var intToString: String = \"\"\n}\n```\n###### Generation result\n```console\ne: [ksp] com.ucasoft.komm.processor.exceptions.KOMMCastException: AutoCast is turned off! You have to use @MapConvert annotation to cast (stringToInt: Int) from (stringToInt: String)\n```\n#### Change Convert Function Name\n###### Classes declaration\n```kotlin\n@KOMMMap(\n    from = [SourceObject::class],\n    config = MapConfiguration(\n        convertFunctionName = \"convertToDestination\"\n    )\n)\ndata class DestinationObject(\n    val id: Int,\n    val stringToInt: Int\n) {\n    var intToString: String = \"\"\n}\n```\n###### Generated extension function\n```kotlin\nfun SourceObject.convertToDestination(): DestinationObject = DestinationObject(\n    id = id,\n    stringToInt = stringToInt.toInt()\n).also { \n    it.intToString = intToString.toString()\n}\n```\n\n### @MapName annotation\n#### Classes declaration\n```kotlin\nclass SourceObject {\n    //...\n    val userName = \"user\"\n}\n\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    //...\n    @MapName(\"userName\")\n    val name: String\n) {\n    var intToString: String = \"\"\n}\n```\nor\n```kotlin\n@KOMMMap(to = [DestinationObject::class])\nclass SourceObject {\n    //...\n    @MapName(\"name\")\n    val userName = \"user\"\n}\n\ndata class DestinationObject(\n    //...\n    val name: String\n) {\n    var intToString: String = \"\"\n}\n```\n#### Generated extension function\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    //...\n    name = userName\n).also { \n    it.intToString = intToString.toString()\n}\n```\n\n### Use Converter\n#### Converter declaration\n```kotlin\nclass CostConverter(source: SourceObject) : KOMMConverter\u003cSourceObject, Double, String\u003e(source) {\n\n    override fun convert(sourceMember: Double) = \"$sourceMember ${source.currency}\"\n}\n```\n#### Classes declaration\n```kotlin\nclass SourceObject {\n    //...\n    val cost = 499.99\n}\n\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    //...\n    @MapConvert\u003cSourceObject, CostConverter\u003e(CostConverter::class)\n    val cost: String\n) {\n    //...\n    @MapConvert\u003cSourceObject, CostConverter\u003e(CostConverter::class, \"cost\")\n    var otherCost: String = \"\"\n}\n```\n#### Generated extension function\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    //...\n    cost = CostConverter(this).convert(cost)\n).also { \n    //...\n    it.otherCost = CostConverter(this).convert(cost)\n}\n```\n### Use Resolver\n#### Resolver declaration\n```kotlin\nclass DateResolver(destination: DestinationObject?) : KOMMResolver\u003cDestinationObject, Date\u003e(destination) {\n    \n    override fun resolve(): Date = Date.from(Instant.now())\n}\n```\n#### Classes declaration\n```kotlin\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    //...\n    @MapDefault\u003cDateResolver\u003e(DateResolver::class)\n    val activeDate: Date\n) {\n    //...\n    @MapDefault\u003cDateResolver\u003e(DateResolver::class)\n    var otherDate: Date = Date.from(Instant.now())\n}\n```\n#### Generated extension function\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    //...\n    activeDate = DateResolver(null).resolve()\n).also { \n    //...\n    it.otherDate = DateResolver(it).resolve()\n}\n```\n### Use NullSubstitute\n#### Mapping configuration\n###### Classes declaration\n```kotlin\n@KOMMMap(\n    from = [SourceObject::class],\n    config = MapConfiguration(\n      allowNotNullAssertion = true\n    )\n)\ndata class DestinationObject(\n    val id: Int\n)\ndata class SourceObject(\n    val id: Int?\n)\n```\n###### Generated extension function\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    id = id!!\n)\n```\n###### Otherwise\n```console\ne: [ksp] com.ucasoft.komm.processor.exceptions.KOMMCastException: Auto Not-Null Assertion is not allowed! You have to use @NullSubstitute annotation for id property.\n```\n#### Resolver declaration\n```kotlin\nclass IntResolver(destination: DestinationObject?): KOMMResolver\u003cDestinationObject, Int\u003e(destination) {\n\n    override fun resolve() = 1\n}\n```\n#### Classes declaration Map From\n```kotlin\n@KOMMMap(\n    from = [SourceObject::class]\n)\ndata class DestinationObject(\n    @NullSubstitute(MapDefault(IntResolver::class))\n    val id: Int\n) {\n    @NullSubstitute(MapDefault(IntResolver::class), \"id\")\n    var otherId: Int = 0\n}\n```\n#### Generated extension function for Map From\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    id = id ?: IntResolver(null).resolve()\n).also {\n    it.otherId = id ?: IntResolver(it).resolve()\n}\n```\n#### Classes declaration Map To\n```kotlin\n@KOMMMap(\n    to = [DestinationObject::class]\n)\ndata class SourceObject(\n    @NullSubstitute(MapDefault(IntResolver::class))\n    val id: Int?\n) \n```\n#### Generated extension function for Map To\n```kotlin\nfun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    id = id ?: IntResolver(null).resolve()\n)\n```\n### Multi Sources Support\n#### Classes declaration\n```kotlin\n@KOMMMap(\n    from = [FirstSourceObject::class, SecondSourceObject::class]\n)\ndata class DestinationObject(\n    @NullSubstitute(MapDefault(IntResolver::class), [FirstSourceObject::class])\n    @MapName(\"userId\", [SecondSourceObject::class])\n    val id: Int\n) {\n    @NullSubstitute(MapDefault(IntResolver::class), \"id\", [FirstSourceObject::class])\n    var otherId: Int = 0\n}\n\ndata class FirstSourceObject(\n  val id: Int?\n)\n\ndata class SecondSourceObject(\n    val userId: Int\n)\n```\nin case, different sources should be configured different:\n```kotlin\n@KOMMMap(\n    from = [FirstSourceObject::class],\n    config = MapConfiguration(\n        allowNotNullAssertion = true\n    )\n)\n@KOMMMap(\n    from = [SecondSourceObject::class]\n)\ndata class DestinationObject(\n  @NullSubstitute(MapDefault(IntResolver::class), [FirstSourceObject::class])\n  @MapName(\"userId\", [SecondSourceObject::class])\n  val id: Int\n) {\n  @NullSubstitute(MapDefault(IntResolver::class), \"id\", [FirstSourceObject::class])\n  var otherId: Int = 0\n}\n```\n#### Generated extension functions\n```kotlin\nfun FirstSourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n    id = id ?: IntResolver(null).resolve()\n).also {\n    it.otherId = id ?: IntResolver(it).resolve()\n}\n\nfun SecondSourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n  id = userId\n)\n```\n\n## Plugins\n\n### Iterable Plugin - Collections Mapping\n#### Add with Gradle\n\n###### JVM Project\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.0-1.0.28\"\n}\n\nval kommVersion = \"0.22.8\"\n\ndepensencies {\n    implementation(\"com.ucasoft.komm:komm-annotations:$kommVersion\")\n    ksp(\"com.ucasoft.komm:komm-processor:$kommVersion\")\n    ksp(\"com.ucasoft.komm:komm-plugins-iterable:$kommVersion\")\n}\n```\n###### Multiplatform Project\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.0-1.0.28\"\n}\n\nval kommVersion = \"0.22.8\"\n\n//...\n\ndependencies {\n    add(\"kspJvm\", \"com.ucasoft.komm:komm-plugins-iterable:$kommVersion\")\n    add(\"kspJvm\", \"com.ucasoft.komm:komm-processor:$kommVersion\")\n    add(\"kspJs\", \"com.ucasoft.komm:komm-plugins-iterable:$kommVersion\")\n    add(\"kspJs\", \"com.ucasoft.komm:komm-processor:$kommVersion\")\n    // Add other platforms like `kspAndroidNativeX64`, `kspLinuxX64`, `kspMingwX64` etc.\n}\n```\n#### Allow NotNullAssertion\n###### Classes declaration\n```kotlin\nclass SourceObject {\n    val intList: List\u003cInt\u003e? = listOf(1, 2, 3)\n}\n\n@KOMMMap(from = [SourceObject::class], config = MapConfiguration(allowNotNullAssertion = true))\ndata class DestinationObject(\n    @MapName(\"intList\")\n    val stringList: MutableList\u003cString\u003e\n)\n```\n###### Generated extension function\n```kotlin\npublic fun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n\tstringList = intList!!.map { it.toString() }.toMutableList()\n)\n```\n#### NullSubstitute\n###### Classes declaration\n```kotlin\nclass SourceObject {\n    val intList: List\u003cInt\u003e? = listOf(1, 2, 3)\n}\n\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    @NullSubstitute(MapDefault(StringListResolver::class), \"intList\")\n    val stringList: MutableList\u003cString\u003e\n)\n```\n###### Generated extension function\n```kotlin\npublic fun SourceObject.toDestinationObject(): DestinationObject = DestinationObject(\n\tstringList = intList?.map { it.toString() }?.toMutableList() ?: StringListResolver(null).resolve()\n)\n```\n\n### Exposed Plugin - ResultRow Mapping\n#### Add with Gradle\n\n###### JVM Project\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"2.1.0-1.0.28\"\n}\n\nval kommVersion = \"0.22.8\"\n\ndepensencies {\n    implementation(\"com.ucasoft.komm:komm-annotations:$kommVersion\")\n    ksp(\"com.ucasoft.komm:komm-processor:$kommVersion\")\n    ksp(\"com.ucasoft.komm:komm-plugins-exposed:$kommVersion\")\n}\n```\n#### Usage\n###### Classes declaration\n```kotlin\nobject SourceObject: Table() {\n    val id = integer(\"id\").autoIncrement()\n    val name = varchar(\"name\", 255)\n    val age = integer(\"age\")\n\n    override val primaryKey = PrimaryKey(id)\n}\n\n@KOMMMap(from = [SourceObject::class])\ndata class DestinationObject(\n    val id: Int,\n    val name: String,\n    val age: Int\n)\n```\n###### Generated extension function\n```kotlin\npublic fun ResultRow.toDestinationObject(): DestinationObject = DestinationObject(\n    id = this[SourceObject.id],\n    name = this[SourceObject.name],\n    age = this[SourceObject.age]\n)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscogun%2Fkomm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscogun%2Fkomm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscogun%2Fkomm/lists"}