
Lightweight library for generating type-safe mappers using annotations and code generation. Features bidirectional mapping, property renaming, custom converters, factory-based construction, and collection handling.
Lightweight annotation-based library for generating type-safe mappers in Kotlin Multiplatform using KSP 2. The
komap-annotations module is KMP-ready, while code generation is performed via KSP in commonMain (metadata) using the
JVM processor komap-processor.
commonMain for JVM/JS/Native, no platform-specific APIs@Komap(from = [...], to = [...])
@MapName("sourceName")
@IgnoreInMapping
@KomapProvider(qualifier = ...) + @MapQualifier("...")
@KomapFactory(qualifier = ...) with selection through factoryQualifiers
Iterable; missing values are exposed as parameters/lambdasPrereqs: Kotlin 2.2.0, KSP 2.2.0-2.0.2, repository mavenCentral().
// settings.gradle.kts
pluginManagement {
repositories { google(); gradlePluginPortal(); mavenCentral() }
}// build.gradle.kts (module with your models)
plugins {
kotlin("multiplatform")
id("com.google.devtools.ksp")
}
kotlin {
jvm()
js { nodejs() }
// add other targets as needed
sourceSets {
val commonMain by getting {
// Include KSP generated sources
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
dependencies {
implementation("ua.wwind.komap:komap-annotations:1.0.0")
}
}
}
}
dependencies {
// Wire the KSP processor for common metadata
add("kspCommonMainMetadata", "ua.wwind.komap:komap-processor:1.0.0")
}Generate code:
./gradlew kspCommonMainKotlinMetadataGenerated sources live in build/generated/ksp/metadata/commonMain/kotlin.
// API model
data class ApiUser(
val id: String,
val name: String,
val role: String,
)
// Domain model with annotations
@Komap(to = [ApiUser::class])
data class User(
@MapName(name = "id") val userId: String,
val name: String,
@IgnoreInMapping val role: String, // not read from source; becomes a mapper parameter
)
// After generation you get:
// fun User.toApiUser(role: String): ApiUser
// fun Iterable<User>.toApiUser(provideRole: (User) -> String): List<ApiUser>Usage:
val user = User(userId = "42", name = "Ada", role = "ADMIN")
val api = user.toApiUser(role = "USER")
val list = listOf(user).toApiUser { it.role }// Example: Email String
@KomapProvider(qualifier = "plain")
fun Email.toStringPlain(): String = this.value
@KomapProvider
fun String.toEmail(): Email = Email(this)
// Use the selected provider
data class Profile(
@MapQualifier("plain") val email: String,
)// Must be in the same module as the target class
@KomapFactory(qualifier = "fromName")
fun ApiUser(name: String, id: String, role: String): ApiUser = ApiUser(id, name, role)
@Komap(to = [ApiUser::class], factoryQualifiers = ["fromName"])
data class User(
@MapName("id") val userId: String,
val name: String,
@IgnoreInMapping val role: String,
)The processor selects a factory by matching return type and provided factoryQualifiers.
komap-annotations): Android (Library), JVM, JS (Node), WASM JS, Linux X64/ARM64, macOS X64/ARM64,
Windows (mingwX64), iOS X64/ARM64/Simulatorkomap-processor): JVM (via KSP in metadata for KMP)See the komap-samples module:
basic/BasicSample.kt — basic mappings and collectionsfactory/FactorySample.kt — factories with qualifiersproviders/ — examples of @KomapProvider
Run generation in the sample:
./gradlew :komap-samples:kspCommonMainKotlinMetadataApache License 2.0. See POM details and the repository page: White Wind LLC — komap.
PRs and discussions are welcome. Please keep the code style and add small examples to komap-samples for new features.
Lightweight annotation-based library for generating type-safe mappers in Kotlin Multiplatform using KSP 2. The
komap-annotations module is KMP-ready, while code generation is performed via KSP in commonMain (metadata) using the
JVM processor komap-processor.
commonMain for JVM/JS/Native, no platform-specific APIs@Komap(from = [...], to = [...])
@MapName("sourceName")
@IgnoreInMapping
@KomapProvider(qualifier = ...) + @MapQualifier("...")
@KomapFactory(qualifier = ...) with selection through factoryQualifiers
Iterable; missing values are exposed as parameters/lambdasPrereqs: Kotlin 2.2.0, KSP 2.2.0-2.0.2, repository mavenCentral().
// settings.gradle.kts
pluginManagement {
repositories { google(); gradlePluginPortal(); mavenCentral() }
}// build.gradle.kts (module with your models)
plugins {
kotlin("multiplatform")
id("com.google.devtools.ksp")
}
kotlin {
jvm()
js { nodejs() }
// add other targets as needed
sourceSets {
val commonMain by getting {
// Include KSP generated sources
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
dependencies {
implementation("ua.wwind.komap:komap-annotations:1.0.0")
}
}
}
}
dependencies {
// Wire the KSP processor for common metadata
add("kspCommonMainMetadata", "ua.wwind.komap:komap-processor:1.0.0")
}Generate code:
./gradlew kspCommonMainKotlinMetadataGenerated sources live in build/generated/ksp/metadata/commonMain/kotlin.
// API model
data class ApiUser(
val id: String,
val name: String,
val role: String,
)
// Domain model with annotations
@Komap(to = [ApiUser::class])
data class User(
@MapName(name = "id") val userId: String,
val name: String,
@IgnoreInMapping val role: String, // not read from source; becomes a mapper parameter
)
// After generation you get:
// fun User.toApiUser(role: String): ApiUser
// fun Iterable<User>.toApiUser(provideRole: (User) -> String): List<ApiUser>Usage:
val user = User(userId = "42", name = "Ada", role = "ADMIN")
val api = user.toApiUser(role = "USER")
val list = listOf(user).toApiUser { it.role }// Example: Email String
@KomapProvider(qualifier = "plain")
fun Email.toStringPlain(): String = this.value
@KomapProvider
fun String.toEmail(): Email = Email(this)
// Use the selected provider
data class Profile(
@MapQualifier("plain") val email: String,
)// Must be in the same module as the target class
@KomapFactory(qualifier = "fromName")
fun ApiUser(name: String, id: String, role: String): ApiUser = ApiUser(id, name, role)
@Komap(to = [ApiUser::class], factoryQualifiers = ["fromName"])
data class User(
@MapName("id") val userId: String,
val name: String,
@IgnoreInMapping val role: String,
)The processor selects a factory by matching return type and provided factoryQualifiers.
komap-annotations): Android (Library), JVM, JS (Node), WASM JS, Linux X64/ARM64, macOS X64/ARM64,
Windows (mingwX64), iOS X64/ARM64/Simulatorkomap-processor): JVM (via KSP in metadata for KMP)See the komap-samples module:
basic/BasicSample.kt — basic mappings and collectionsfactory/FactorySample.kt — factories with qualifiersproviders/ — examples of @KomapProvider
Run generation in the sample:
./gradlew :komap-samples:kspCommonMainKotlinMetadataApache License 2.0. See POM details and the repository page: White Wind LLC — komap.
PRs and discussions are welcome. Please keep the code style and add small examples to komap-samples for new features.