mcarleio/konvert

Example for custom type converters

b-heimann-senacor opened this issue · 2 comments

Could you provide instructions on how to register a custom type converter, e.g. to convert a String to a Currency field?

@KonvertTo(Account::class)
data class AccountDto(val amount: String, val currency: String)

data class Account(val amount: String, val currency: java.util.Currency)

class StringToCurrencyConverter : BaseTypeConverter(String::class, java.util.Currency::class) {
    override fun convert(fieldName: String, nc: String): String = 
        "$fieldName$nc.let·{ java.util.Currency.getInstance(it) }"
}

According to the documentation, the type converter must be on the KSP classpath: https://mcarleio.github.io/konvert/modules.html#to-extend-the-functionality-of-konvert-the-following-modules-are-provided

  • konvert-converter-api

This module can be used to build your own TypeConverters to be used by Konvert during compilation. As Konvert is using SPI, >you can build your own library and just include it into KSP classpath! (TODO: reference example)

How can I do this?

Also, is it possible to enable one of the provided TypeConverters globally, that is not enabled by default?
E.g. String -> BigDecimal TypeConverter,

Ok, so regarding TypeConverter:

  1. If you just need a custom TypeConverter for one single project, you probably do not need to write a "real" TypeConverer. Instead, you can do the following:
@Konverter
interface MyCustomConverter {
   fun stringToCurrency(str: String): Currency {
       return Currency.getInstance(str)
   }
}

Konvert registers all @KonverTo, @KonvertFrom and @Konvert/@Konverter functions as TypeConverters during KSP run. It even works between multiple modules, e.g. when you have a module A where you define the MyCustomConverter and a module B which depends on module A where you have a mapping from String->Currency, then Konvert knows the MyCustomConverter and will use it.

@KonvertTo(Target::class)
data class Source(val currency: String)
data class Target(val currency: Currency)

Konvert will then generate something like this:

import io.mcarle.konvert.api.Konverter

public fun Source.toTarget(): Target = Target(
  currency = Konverter.get<MyCustomConverter>().stringToCurrency(str = currency)
)
  1. If you nevertheless need or want to build a custom TypeConverter so that you can use it in various projects, have more control on the generated code, or want to map differently than konvert does, or you do not want to have a dependency on konvert in runtime: Have a look at the converter module of konvert. It is exactly what you have to build. I will document it in the future.

  2. Regarding enabling TypeConverters globally, there is no such configuration yet. But it is planned to do so. For now, you either have to enable it per Mapping, or you can write your own String->BigDecimal function as shown in 1.

Thank you, the first option works fine.