kautoMapper
2.1.3indexedAnnotations enabling compile-time generation of mappers between data models, with property renaming, default values, custom mapping functions, parent-based mapping, opt-ins and visibility control.
Annotations enabling compile-time generation of mappers between data models, with property renaming, default values, custom mapping functions, parent-based mapping, opt-ins and visibility control.
This package provides annotation definitions for the AutoMapper KSP Processor, allowing automatic mapping generation between Kotlin classes for Kotlin Multiplatform, Android, and * iOS*.
It includes:
commonMainimplementation("io.github.the-best-is-best:automapper-annotations:2.1.3")
Add KSP processor:
ksp("io.github.the-best-is-best:automapper-processor:2.1.3")
./gradlew composeApp:kspCommonMainKotlinMetadata
@AutoMapper@Repeatable
annotation class AutoMapper(
val to: KClass<*>,
val useClassNameInMapperFunc: Boolean = false,
val optIns: Array<String> = [],
val ignoreKeys: Array<String> = [],
val forcePublic: Boolean = false,
val defaultValues: Array<DefaultValue> = [],
reverse: =
)
@DefaultValuevalue string.
annotation class DefaultValue(
val key: String,
val value: String
)
Advanced Features:
The processor automatically detects and imports classes used in the value string if they match the
type of the target property or other properties in the class.
Example:
@AutoMapper(
to = UserModel::class,
defaultValues = [
DefaultValue("name", "\"John Doe\""), // String literal (needs escaped quotes)
DefaultValue("isActive", "true"), // Boolean
DefaultValue("status", "Status.ACTIVE") // Enum (Status will be auto-imported)
]
)
Generation Logic:
target = defaultValuetarget = source ?: defaultValue@AutoMapperName@Repeatable
annotation class AutoMapperName(
val to: String,
val mapTo: KClass<*> = Any::class
)
Example:
@AutoMapperName("addres", mapTo = UserModel::class)
@AutoMapperName("address_entity", mapTo = UserEntity::class)
val address: AddressDto
@AutoMapperRequiredUse this when you are certain a nullable source property will not be null at runtime when mapping to
a non-nullable target. It will use the !! operator in the generated code.
@Repeatable
annotation class AutoMapperRequired(
val mapTo: KClass<*> = Any::class
)
Example:
@AutoMapperRequired(mapTo = UserModel::class) // Only applies '!!' when mapping to UserModel
val joinDate: String?
@AutoMapperAddOptInsannotation class AutoMapperAddOptIns(val value: Array<String>)
@AutoMapperAddImportannotation class AutoMapperAddImport(val value: Array<String>)
You can define custom mapping logic in your class or companion object without any property annotations. The processor will automatically find these functions based on their names and types.
Use map[PropertyName] for forward and reverseMap[PropertyName] for reverse.
fun mapJoinDate(value: String): LocalDateTime
fun reverseMapJoinDate(value: LocalDateTime): String
You can define mappers based on the Target Type. This is useful for reusing logic across multiple properties of the same type.
// Forward: maps any property targeting LocalDateTime
fun mapToLocalDateTime(value: String): LocalDateTime
// OR include source type for more clarity
fun mapFromStringToLocalDateTime(value: String): LocalDateTime
// Reverse: maps any property targeting String from LocalDateTime
fun : String
Explicitly define mappers between two specific types for maximum clarity.
// Forward: String -> LocalDateTime
fun mapStringToLocalDateTime(value: String): LocalDateTime
// OR
: LocalDateTime
: String
: String
For List<T> or Array<T>, you can define a mapper for the list itself using
mapFromList[ArgTypeName]ToList[TargetArgTypeName] or mapList[ArgTypeName].
// Forward: List<LookupResponse> -> List<Int>
fun mapFromListLookupResponseToListInt(data: List<LookupResponse>?): List<Int>?
// OR simpler
fun mapListLookupResponse(data: List<LookupResponse>?): List<Int>?
If the function takes the Source Class itself as a parameter, it acts as a "from parent" mapper.
fun mapEmails(data: UserDto): List<String>
If you have multiple @AutoMapper targets, you can specify which target a function applies to using
map[PropertyName]To[TargetClassName].
@AutoMapper(to = UserModel::class)
@AutoMapper(to = UserEntity::class)
data class UserDto(...) {
companion object {
// Only used when mapping to UserEntity
fun mapJoinDateToUserEntity(value: ):
: LocalDateTime
}
}
val userDto = UserDto(...)
// Forward mapping
val model: UserModel = userDto.toUserModel()
val entity: UserEntity = userDto.toUserEntity()
// Reverse mapping
val dtoFromModel: UserDto = model.toUserDto()
val dtoFromEntity: UserDto = entity.toUserDto()
id("com.google.devtools.ksp")
kotlin {
// ... targets configuration (android, ios, etc.)
sourceSets.named("commonMain").configure {
// Ensure generated code is visible
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
}
ksp {
// Optional: make mappers internal by default
arg("autoMapperVisibility", "false")
}
build/generated/ksp/metadata/commonMain/kotlinuseClassNameInMapperFunc = true to avoid name collisions in
extension functions.
data class UserDto constructor(
val id: Int,
val name: String,
val joinDate: String,
val address: AddressDto,
val emails: List<String>,
val phoneNumbers: List<PhoneNumberDto>,
val role: Roles,
val status: Status
) {
companion object {
// 1. mapTo[Type] convention - Used for any property mapping to LocalDateTime
fun mapToLocalDateTime(date: String): LocalDateTime = LocalDateTime.parse(date)
// 2. Target-Specific - Used for 'joinDate' specifically when mapping to UserEntity
fun mapJoinDateToUserEntity(date: String): Long =
LocalDateTime.parse(date).toInstant(TimeZone.UTC).toEpochMilliseconds()
// 3. reverseMapFrom[Type] - Used when mapping back from UserModel
fun reverseMapFromLocalDateTime(date: LocalDateTime): String = date.toString()
// 4. Custom logic using the whole parent object
fun mapEmails(data: UserDto): List<String> = data.emails.filter { it.isNotBlank() }
}
}
Surfaced from shared tags and platforms — no rankings paid for.