Options

Konvert provides a few options, which you can define either globally for the complete run, or per mapping.

How to set options

Globally with Gradle

If you use gradle, you can define options using the ksp block:

ksp {
    arg("konvert.konverter.generate-class", "true")
}

Globally with Maven

If you use maven together with the com.dyescape:kotlin-maven-symbol-processing dependency (as shown here TODO), you can add options to your pom.xml in the <configuration> block of kotlin-maven-plugin:

<pluginOptions>
    <option>ksp:apoption=konvert.konverter.generate-class=true</option>
</pluginOptions>

Local for one annotation

The annotations @Konverter, @Konvert, @KonvertTo and @KonvertFrom all offer the possibility to set options. The processing of these annotations will run with a copy of the inherited options (e.g. globally set ones) combined with their defined options. In case you have options in @Konverter and @Konvert, then the later one will inherit the other options and override/complement with its own.

@Konverter(options=[
    Konfig(key="konvert.enforce-not-null", value="true")
])

Available Options

Tip
Have a look in the package io.mcarle.konvert.api.config for all provided options.

General Options

Option Possible values Default Description

konvert.enforce-not-null

true/false

false

When set to true, all TypeConverter which respect this setting:

  • will match, when the source type is nullable but the target type is not

  • will add !! to the generated code, to enforce the result to be not null

Example
@KonvertTo(Person::class, options=[
    Konfig(key="konvert.enforce-not-null", value="true")
])
class PersonDto(val name: String?)
class Person(val name: String)

Will generate:

fun PersonDto.toPerson() = Person(name = name!!)

konvert.generated-filename-suffix

any string

Konverter

This setting will change the suffix/trailing part of the generated filenames.

Example
@KonvertTo(PersonDto::class, options=[
    Konfig(key="konvert.generated-filename-suffix", value="_XX")
])
class Person(val name: String)
class PersonDto(val name: String)

Will generate a file Person_XX.kt instead of PersonKonverter.kt

konvert.add-generated-konverter-annotation

true/false

true

This setting will add the @GeneratedKonverter annotation on the generated functions. Together with a generated Konvert module file referencing all generated functions FQN, this annotation is used to reuse previously generated konverter functions from other modules or libraries. If you do not want your generated konverter functions to be reused in other modules, you can turn this setting globally or per annotation.

Example
@KonvertTo(PersonDto::class, priority = 123)
class Person(val name: String)
@KonvertTo(Person::class, options=[
    Konfig(key="konvert.add-generated-konverter-annotation", value="false")
])
class PersonDto(val name: String)

Will generate:

@GeneratedKonverter(priority = 123)
fun Person.toPersonDto() = PersonDto(name = name)
fun PersonDto.toPerson() = Person(name = name)

konvert.enable-converters

list of TypeConverter names divided by comma or semicolon

empty list

All listed TypeConverter names are registered to be enabled in the current context. This can be useful if you need a certain TypeConverter, e.g. StringToIntConverter, a lot of times and do not want to enable it on each field mapping via @Mapping.

Example
@KonvertTo(PersonDto::class, options=[
    Konfig(key="konvert.enable-converters", value="StringToIntConverter, StringToLocalDateConverter")
])
class Person(val age: String, val birthday: String)
class PersonDto(val age: Int, val birthday: LocalDate)

konvert.konverter.use-reflection

true/false

false

When set to true (deprecated), Konvert will generate code that uses reflection during runtime to determine the actual implementation of a @Konverter annotated interface. As Konvert aims to support KMP, reflection is not an option there anymore.

Otherwise, it will generate code that uses the generated implementation directly.

Example
@Konverter
interface PersonMapper {
    fun toDto(person: Person): PersonDto
}

class Person(val age: String)
class PersonDto(val age: String)

@KonvertTo(GroupDto::class, mapFunctionName="toGroupWithReflection", options=[
    Konfig(key="konvert.konverter.use-reflection", value="true")
])
@KonvertTo(GroupDto::class, mapFunctionName="toGroupWithoutReflection")
class Group(val members: List<Person>)
class GroupDto(val members: List<PersonDto>)

Will generate the following extension functions for Group:

fun Group.toGroupWithReflection() = GroupDto(
  members = members.map { Konverter.get<PersonMapper>().toDto(it) }
)

fun Group.toGroupWithoutReflection() = GroupDto(
  members = members.map { PersonMapperImpl.toDto(it) }
)

konvert.generatedModuleSuffix

any string

UUID.randomUUID()

Only effective if set globally. This setting defines the suffix for the generated module type.

Any non word character will be replaced with an empty string.

konvert.parseDeprecatedMetaInfFiles

true/false

false

Only effective if set globally. This setting defines if the deprecated META-INF files should be parsed to load generated konverter functions.

Will be removed in one of the next releases.

konvert.non-constructor-properties-mapping

auto, explicit, implicit, all

auto

Controls how properties of the target class that are not part of the constructor (i.e., mutable properties, properties with setters, or properties defined outside the primary constructor) are mapped.

  • auto (default): If there are no @Mapping annotations (except those with ignore = true), behaves like implicit. If there are any @Mapping annotations, behaves like explicit.

  • explicit: Only non-constructor target properties that are explicitly declared via @Mapping will be mapped. All others are ignored, even if a matching source property exists.

  • implicit: All non-constructor target properties for which a matching source property exists (by name), or for which a @Mapping is defined, will be mapped. All others are ignored.

  • all: All non-constructor target properties must be mapped. If a property cannot be mapped (no matching source property and no @Mapping), an exception is thrown.

Example
class Source(val id: String) {
    var description: String? = null
    var additional: String? = null
}

class Target(val id: String) {
    var description: String? = null
    var extra: String? = null
}

@Konverter
interface MapperAuto {
    fun map(source: Source): Target
}

@Konverter(options=[
    Konfig(key="konvert.non-constructor-properties-mapping", value="implicit")
])
interface MapperImplicit {
    fun map(source: Source): Target
}

@Konverter(options=[
    Konfig(key="konvert.non-constructor-properties-mapping", value="explicit")
])
interface MapperExplicit {
    fun map(source: Source): Target
}

@Konverter(options=[
    Konfig(key="konvert.non-constructor-properties-mapping", value="all")
])
interface MapperAll {
    fun map(source: Source): Target
}

Will result in:

  • MapperAuto and MapperImplicit will generate the same code, which only maps id and description properties

  • MapperExplicit will only map id, as there are no @Mapping annotations defined

  • MapperAll will throw an exception, as extra has no matching source property and no @Mapping defined

konvert.invalid-mapping-strategy

warn, fail

warn

Determines how Konvert handles invalid mapping definitions.

  • warn (default): Konvert logs a warning for each invalid mapping, ignores it, and continues code generation.

  • fail: Konvert will throw an exception and fail the build

An invalid mapping occurs when:

  • A mapping references a source property that does not exist in the source type.

  • A mapping references a target property that does not exist in the target type.

  • A mapping defines incompatible parameters (e.g., both source and ignore = true).

  • There are multiple mappings for the same target property.

@Konverter Options

Option Possible values Default Description

konvert.konverter.generate-class

true/false

false

When set to true, Konvert will generate a class instead of an object.

Example
@Konverter(options=[
    Konfig(key="konvert.konverter.generate-class", value="true")
])
interface PersonMapper {
    fun toDto(person: Person): PersonDto
}

class PersonDto(val name: String)
class Person(val name: String)

Will generate:

class PersonMapperImpl: PersonMapper {
    override fun toDto(person: Person): PersonDto = PersonDto(name = person.name)
}

Injector Options

Anvil

Option Possible values Default Description

konvert.anvil.default-injection-method

DISABLED, FACTORY, SINGLETON

DISABLED

Append some injection method by default to all generated mapper classes. Requires konvert.anvil.default-scope to be set as well!

konvert.anvil.default-scope

fully qualified class name

-

Has to be set to qualified name of anvil scope class, like AppScope. Only used when konvert.anvil.default-injection-method not disabled.

Example

Global settings (e.g. in build.gradle.kts or pom.xml):

  • konvert.anvil.default-injection-method = SINGLETON

  • konvert.anvil.default-scope = AppScope

abstract class AppScope private constructor()

@Konverter
interface PersonMapper {
    fun toDto(person: Person): PersonDto
}
class Person(val name: String)
class PersonDto(val name: String)

Will generate:

@ContributesBinding(scope = AppScope::class)
@Singleton
class PersonMapperImpl: PersonMapper {
    @Inject
    public constructor()

    override fun toDto(person: Person): PersonDto = PersonDto(name = person.name)
}

Koin

Option Possible values Default Description

konvert.koin.default-injection-method

DISABLED, FACTORY, SINGLE, SCOPE

DISABLED

Append some injection method by default to all generated mapper classes. Requires konvert.koin.default-scope to be set as well!

konvert.koin.default-scope

fully qualified class name or any string

-

Use this scope by default when konvert.koin.default-injection-method is set to scope.

  • If value is fully qualified class identifier it will be used as @Scope(ProvidedType::class).

  • If value is string - it will be used as named scope, like @Scope(name = "ProvidedName")

Example

Global settings (e.g. in build.gradle.kts or pom.xml):

  • konvert.koin.default-injection-method = SINGLE

@Konverter
interface PersonMapper {
    fun toDto(person: Person): PersonDto
}
class Person(val name: String)
class PersonDto(val name: String)

Will generate:

@Single
class PersonMapperImpl: PersonMapper {
    override fun toDto(person: Person): PersonDto = PersonDto(name = person.name)
}