ansman/kotshi

Polymorphism support

rodolfodpk opened this issue · 2 comments

Hi. Here is my use case: I have these interfaces bellow and I have many data classes implementing these interfaces. I'm using Jackson and after registering the KotlinModule into ObjectMapper, I'm able to ser/der List<DomainEvent> and List<Command>, etc. I would like to use code generation instead (avoiding kotlin-reflect library). Is there a way to do this using Kotshi or even Moshi?

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
interface DomainEvent

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
interface EntityId {
  fun value(): Int
}

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
interface Command {
  val commandId: UUID
  val targetId: EntityId
}

Thanks

There is no built in support in Moshi for this so Kotshi doesn't support it either.

You could try doing something like this

/**
 * Add a [JsonAdapter] for the source type that will delegate to the adapter for the delegate type.
 * This is useful when you want to (de)serialize an interface as a concrete type.
 * 
 * @param source The source type.
 * @param delegateType The delegate's type.
 */
fun Moshi.Builder.addDelegate(source: Type, delegateType: Type): Moshi.Builder =
    add { type, annotations, moshi ->
        if (Types.equals(source, type)) moshi.adapter<Any>(delegateType, annotations) else null
    }

val moshi = Moshi.Builder()
  .addDelegate(DomainEvent::class.java, SomeImplementation::class.java)
  .add(MyKotshiFactory.INSTANCE)
  .build()

Thanks, I will try it.