Я использую Gson v2.8.2 и Retrofit v2.3.0, и у меня есть два класса, Answer.kt:
open class Answer(@SerializedName("answer")
var text: String,
val id: Int)
и AnswerSummary.kt:
class AnswerSummary(val answer: Answer) : Answer(answer.text, answer.id) {
val percent: Int = 0
}
Я использую его в списке (на Java, все еще перехожу на Kotlin):
public List<AnswerSummary> getAnswerSummaries() {
return answerSummaries;
}
Я получаю сообщение об ошибке, когда val не удаляется: 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)
....
После удаления val: class AnswerSummary(answer: Answer) ... ошибка исчезнет. Почему это так, если я аннотировал только одно поле? - @SerializedName("answer") var text: String.
Я нашел способ обойти сбой, сохранив неизменность ('val') - используя другое имя переменной: class AnswerSummary(val ans: Answer) .... Что происходит за фоном - связано ли это с тем, что значение поля @SerializedName совпадает с именем переменной?
Я упомянул, что обхожу сбой, когда использую другое имя переменной: class AnswerSummary(val ans: Answer), я спрашиваю, что происходит: Зачем нужно ли мне удалить 'val' или изменить имя переменной?
Потому что дооснащение Невозможно создать конвертер для класса com.name.app.model.response.AnswerResponse из-за AnswerSummary объявляет несколько полей JSON с именем answer. Что бы вы сделали на месте дооснащения? :)
Попробуйте переименовать параметр answer:
class AnswerSummary(val ans: Answer) : Answer(ans.text, ans.id) { ... }
или используйте answer как параметр, а не свойство:
class AnswerSummary(answer: Answer) : Answer(answer.text, answer.id) { ... }
Это будет работать, потому что, когда вы используете val, параметр 'answer' рассматривается как свойство (без val он считается параметром) и сериализуется Gson с использованием имени свойства как сериализованного имени. В то же время у вас есть такое же сериализованное имя @SerializedName("answer") в вашем базовом классе Answer, поэтому возникает конфликт при сериализации свойств.
почему я должен переименовать переменную? это потому, что @SerializedName также является «ответом»?
да, ошибка «class com.name.app.model.pojo.AnswerSummary объявляет несколько полей JSON с именем answer» говорит о наличии нескольких полей с именем answer
использование аннотации @Expose по-прежнему приводит к сбою приложения. что, если сериализованное значение поля было изменено (в backend api) на "ОТВЕЧАТЬ" вместо "отвечать", знаете ли вы, поможет ли это избежать сбоя? Я знаю, что могу переименовать параметр, но ответ намного чище, чем ans или answerParam. Мой вариант резервного копирования - удалить val, потому что сбои происходят только тогда, когда я добавляю val.
Я думаю, что переименование сериализованного значения в backend api на «ANSWER» может помочь, но я не уверен, вы можете попробовать.
да, я считаю, что ты прав. как получилось, что всякий раз, когда я удаляю «val» из сигнатуры метода, ошибка исчезает. почему "val" вызывает проблему?
Я думаю, это потому, что, когда вы используете val, он рассматривается как свойство (без val он считается параметром) и сериализуется Gson с использованием имени свойства как сериализованного имени. В то же время у вас есть такое же сериализованное имя @SerializedName("answer") в вашем базовом классе Answer , поэтому возникает конфликт при сериализации свойств.
@chornge, я отредактировал свой ответ относительно использования аннотации Expose. Пожалуйста, проверьте, работает ли это для вас.
по-прежнему вылетает с @Expose, вы можете отредактировать свой ответ, включив объяснение использования 'val'.
AnswerSummary declares multiple JSON fields named answerПереименуйтеval answerвAnswerSummary(val answer: Answer)во что-нибудь другое.