google / gson

A Java serialization/deserialization library to convert Java Objects into JSON and back
Apache License 2.0
23.3k stars 4.28k forks source link

Gson cannot serialize subclass who override a field #2638

Open SannaK opened 7 months ago

SannaK commented 7 months ago

I saw some others threads about it but I did not find a solution in them.

Gson version

2.10.1

Java / Android version

17

Description

The real context

I have a sealed class (heritance from Throwable) who represent all errors in my app (~80 inner dataclass). Sometime I want to override "message" or "reason" in my "sub dataclass", but when i try to serialize it with, an error occurs.

A simple way to reproduce

    open class MyClass {
        open val a = 22
    }
    open class SubClass : MyClass() {
        override val a = 25
        val b = 12
    }

Expected behavior

Actual behavior

It cannot serialize SubClass, "JSON fields named 'a'; conflict is caused by fields ...". Also i tried handmade reflection on "SubClass" and i see "a" only one time. I guess you are using more complex mecanics.

Notes:

Reproduction steps

Just run an unit test with the code below and call the methode Builder().toJson(SubClass())

Exception stack trace

Class com.organisation.app.MyUnitTest$SubClass declares multiple JSON fields named 'a'; conflict is caused by fields com.organisation.app.MyUnitTest$SubClass#a and com.organisation.app.MyUnitTest$MyClass#a
java.lang.IllegalArgumentException: Class com.organisation.app.MyUnitTest$SubClass declares multiple JSON fields named 'a'; conflict is caused by fields com.organisation.app.MyUnitTest$SubClass#a and com.organisation.app.MyUnitTest$MyClass#a
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:302)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)
    at com.google.gson.Gson.getAdapter(Gson.java:556)
    at com.google.gson.Gson.toJson(Gson.java:834)
    at com.google.gson.Gson.toJson(Gson.java:812)
    at com.google.gson.Gson.toJson(Gson.java:759)
Marcono1234 commented 7 months ago

Also i tried handmade reflection on "SubClass" and i see "a" only one time

Are you using Java reflection or Kotlin reflection? Possibly Kotlin reflection is hiding the fact that there are multiple fields with the same name.

This might be the same as #2453. Currently Gson is mainly targeting Java, it might also work fine for many cases with Kotlin but there is no proper support for it at the moment.

If possible it might be better if you used a library with explicit Kotlin support, such as Jackson (which you already tried), https://github.com/square/moshi or https://github.com/Kotlin/kotlinx.serialization.