I am using Gson v2.8.2 and Retrofit v2.3.0 and I have two classes, Answer.kt:
open class Answer(@SerializedName("answer")
var text: String,
val id: Int)
and AnswerSummary.kt:
class AnswerSummary(val answer: Answer) : Answer(answer.text, answer.id) {
val percent: Int = 0
}
I am using it in a list (in Java, still migrating to Kotlin):
public List<AnswerSummary> getAnswerSummaries() {
return answerSummaries;
}
I get an error when val
is not removed: class AnswerSummary(val answer: Answer) ...
:
java.lang.IllegalArgumentException: Unable to create converter for class com.name.app.model.response.AnswerResponse
....
Caused by java.lang.IllegalArgumentException: class com.name.app.model.pojo.AnswerSummary declares multiple JSON fields named answer
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
....
After removing 'val': class AnswerSummary(answer: Answer) ...
, the error goes away. Why is this, since I only annotated one field? - @SerializedName("answer") var text: String
.
I found a way to circumvent the crash while still maintaining immutability ('val') - By using a different variable name: class AnswerSummary(val ans: Answer) ...
. What is happening behind the background - is it related to the fact that the @SerializedName field value is the same as the variable name?
Try to rename the answer
parameter:
class AnswerSummary(val ans: Answer) : Answer(ans.text, ans.id) { ... }
or use answer
as parameter, not property:
class AnswerSummary(answer: Answer) : Answer(answer.text, answer.id) { ... }
It will work because when you are using val
parameter 'answer' is considered as a property (without val
it is considered as parameter) and serialized by Gson using property name as serialized name. At the same time you have the same serialized name @SerializedName("answer")
in your base class Answer
, therefore there is a conflict while properties are being serialized.