Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.38k stars 620 forks source link

Wrong serialization if base class is put in external library #997

Closed rwsbillyang closed 4 years ago

rwsbillyang commented 4 years ago

Describe the bug Wrong serialization if base class is put in external library

To Reproduce


//Putting Box here, works fine, but putting external library works bad 
@Serializable
abstract class Box(
    var code: String,
    var msg: String?
){
    constructor(): this(OK, null)
    companion object{
        const val OK = "OK"
        const val KO = "KO"
    }
}

@Serializable
data class Person(val name: String)

 //inheritance from external library,  works bad 
@Serializable
data class PersonListBox1(val list: List<Person>?, val total: Int = 0) :  com.github.rwsbillyang.apiJson.Box()

//inheritance from same file,  works fine
@Serializable
data class PersonListBox2(val list: List<Person>?, val total: Int = 0) : Box()

fun main()
{
//  val json = Json{ serialModule = libSerializersModule + mySerializersModule    } //same output
    val json = Json{}

    val list = listOf(Person("Tom"), Person("Joe"))
    val size = list.size
    val box1 = PersonListBox1(list, size)
    val box2 = PersonListBox2(list, size)

    println("box1: code=${box1.code},msg=${box1.msg},total=${box1.total}")
    val str1 = json.stringify(PersonListBox1.serializer(), box1) // inheritance from external library
    println("box1 json: $str1") //wrong keys: {"list":"OK","total":null,"list":[{"name":"Tom"},{"name":"Joe"}],"total":2}

    println()
    println("box2: code=${box2.code},msg=${box2.msg},total=${box2.total}")
    val str2 = json.stringify(PersonListBox2.serializer(), box2)// inheritance from same project
    println("box2 json: $str2") //correct output as expected: :{"code":"OK","msg":null,"list":[{"name":"Tom"},{"name":"Joe"}],"total":2}
}

output:

box1: code=OK,msg=null,total=2
box1 json: {"list":"OK","total":null,"list":[{"name":"Tom"},{"name":"Joe"}],"total":2}

box2: code=OK,msg=null,total=2
box2 json: {"code":"OK","msg":null,"list":[{"name":"Tom"},{"name":"Joe"}],"total":2}

The serialization of box1 should be same as box2.

or my SerializersModule configuration wrong?

// in external library
@ImplicitReflectionSerializer
val libSerializersModule = SerializersModule {
    polymorphic(Box::class) {
        subclass<DataBox>()
    }
}

//in application project 
@ImplicitReflectionSerializer
val mySerializersModule = SerializersModule {
    polymorphic(Box::class) {
        subclass<PersonListBox1>()
    }
}

Expected behavior Putting base class in external lib and putting in same project should be have same serialization output.

Environment

elizarov commented 4 years ago

Please, recheck with the latest version of serialization in Kotiln 1.4.0. It should have been fixed.

rwsbillyang commented 4 years ago

Please, recheck with the latest version of serialization in Kotiln 1.4.0. It should have been fixed.

Yes, it has been fixed after I upgrade my project to Kotiln 1.4.0 & kotlinx-serialization 1.0.0-RC.

Thanks for the great project.