Search code examples
kotlinserializationjacksoninline

Kotlin Convert Genertic Class to Map


there is a A Data Class

data class A(val x: String?, val y: Int?)

and I have to one two and if there're null value in one then replace it two's property value but if not null then remain one's value

val one = A(null, 3) 
val two = A("11", 4)

A("11", 3)

The idea I came up with is convert two A object to Map and merge two Map and then deserialize merged Map to A

My question is

  1. is there any best idea merge two object?(My Situation)
  2. How to convert Generic Class To Map
inline fun <reified T> toJsonObject(value: T): Map<String, Any> =
        objectMapper.readValue(objectMapper.writeValueAsString(value), Map::class.java)

this does not working please help me..


Solution

  • This is possible only with reflection:

    import kotlin.reflect.full.declaredMembers
       
    inline fun <reified T> T.takeValuesIfNullFrom(item: T): T {
      if(this!!::class != item!!::class) return this
      val constructor = T::class.constructors.first()
      val parameterNames = constructor.parameters.map { parameter -> parameter.name }
      val arguments = T::class.declaredMembers
        .filter { it.name in parameterNames }
        .map { it.call(if (it.call(this) == null) item else this) }
      return constructor.call(*arguments.toTypedArray())
    }
    

    Test:

    data class A(val x: String?, val y: Int?)
    
    val one = A(null, 3)
    val two = A("11", 4)
    
    data class B(val x: String?, val y: Int?, val z: Float?)
    
    val three = B(null, 5, null)
    val four = B("22", 6, 123.456f)
    
    val resultA = one.takeValuesIfNullFrom(two)
    println(resultA)
    
    val resultB = three.takeValuesIfNullFrom(four)
    println(resultB)
    

    Output:

    A(x=11, y=3)
    B(x=22, y=5, z=123.456)