/kdatamapper

The Kotlin Data Mapper (KDataMapper) is a Kotlin Symbol Processing plugin that can generate extension functions to map fields of one class to the primary constructor of another class.

Primary LanguageKotlinApache License 2.0Apache-2.0

KDataMapper

Maven Central

The Kotlin Data Mapper (KDataMapper) is a Kotlin Symbol Processing plugin that can generate extension functions to map fields of one class to the primary constructor of another class.

How To Use

Let's say we have the following entity:

data class ArticleEntity(
    val id: Long,
    val title: String,
    val content: String,
    val tags: List<String> = emptyList(),
)

Now we want to have DTOs for create and update entity:

data class ArticleCreateDto(
    val title: String,
    val content: String,
    val tags: List<String> = emptyList(),
)

data class ArticleUpdateDto(
    val id: Long,
    val title: String,
    val content: String,
    val tags: List<String>,
)

To create mapping functions, you need to add the @KDataMapper annotation and there are several options for this:

  • Add annotation to the ArticleEntity and set fromClasses = [ArticleCreateDto::class, ArticleUpdateDto::class] in the @KDataMapper annotation
@DataMapper(
    fromClasses = [ArticleCreateDto::class, ArticleUpdateDto::class],
)
data class ArticleEntity(
    val id: Long,
    val title: String,
    val content: String,
    val tags: List<String> = emptyList(),
)
  • Or add annotations to DTOs and set toClasses = [ArticleEntity::class] in each @KDataMapper annotation
@DataMapper(
    toClasses = [ArticleEntity::class],
)
data class ArticleCreateDto(
    val title: String,
    val content: String,
    val tags: List<String> = emptyList(),
)

@DataMapper(
    toClasses = [ArticleEntity::class],
)
data class ArticleUpdateDto(
    val id: Long,
    val title: String,
    val content: String,
    val tags: List<String>,
)

When we build the project we'll have:

public fun ArticleCreateDto.toArticleEntity(id: Long) = ArticleEntity(
    id = id,
    title = title,
    content = content,
    tags = tags,
)

public fun ArticleUpdateDto.toArticleEntity() = ArticleEntity(
    id = id,
    title = title,
    content = content,
    tags = tags,
)

The id parameter has been added to the ArticleCreateDto.toArticleEntity function because it's required in ArticleEntity and has no default value.

Next, we want get a DTO with additional field that are not in ArticleEntity:

@DataMapper(
    fromClasses = [ArticleEntity::class],
)
data class ArticleWithCommentsDto(
    val id: Long,
    val title: String,
    val bookmarkCount: Int,
    val comments: List<String> = emptyList(),
)

After build we get:

public fun ArticleTitleDto.toArticleWithCommentsDto(bookmarkCount: Int, comments: List<String>) =
    ArticleWithCommentsDto(
        id = id,
        title = title,
        bookmarkCount = bookmarkCount,
        comments = comments,
    )

public fun ArticleTitleDto.toArticleWithCommentsDto(bookmarkCount: Int) = ArticleWithCommentsDto(
    id = id,
    title = title,
    bookmarkCount = bookmarkCount,
)

Two functions are generated because the comments field have a default value.

You can find a complete project example in the example subdirectory.

Setup

Add KSP plugin to your module's build.gradle.kts:

plugins {
    id("com.google.devtools.ksp") version "1.9.22-1.0.16"
}

Add Maven Central to the repositories blocks in your project's build.gradle.kts:

repositories {
    mavenCentral()
}

Add KDataMapper dependencies:

dependencies {
    implementation("io.github.darkxanter:kdatamapper-core:0.2.0")
    ksp("io.github.darkxanter:kdatamapper-processor:0.2.0")
}

License

Copyright 2023 Sergey Shumov

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.