Ошибка сериализации gson с val в котлине

Я использую 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 совпадает с именем переменной?

AnswerSummary declares multiple JSON fields named answer Переименуйте val answer в AnswerSummary(val answer: Answer) во что-нибудь другое.
Onik 16.11.2018 20:03

Я упомянул, что обхожу сбой, когда использую другое имя переменной: class AnswerSummary(val ans: Answer), я спрашиваю, что происходит: Зачем нужно ли мне удалить 'val' или изменить имя переменной?

chornge 16.11.2018 20:06

Потому что дооснащение Невозможно создать конвертер для класса com.name.app.model.response.AnswerResponse из-за AnswerSummary объявляет несколько полей JSON с именем answer. Что бы вы сделали на месте дооснащения? :)

Onik 16.11.2018 20:08
1
3
858
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте переименовать параметр 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 также является «ответом»?

chornge 16.11.2018 21:57

да, ошибка «class com.name.app.model.pojo.AnswerSummary объявляет несколько полей JSON с именем answer» говорит о наличии нескольких полей с именем answer

Sergey 16.11.2018 22:17

использование аннотации @Expose по-прежнему приводит к сбою приложения. что, если сериализованное значение поля было изменено (в backend api) на "ОТВЕЧАТЬ" вместо "отвечать", знаете ли вы, поможет ли это избежать сбоя? Я знаю, что могу переименовать параметр, но ответ намного чище, чем ans или answerParam. Мой вариант резервного копирования - удалить val, потому что сбои происходят только тогда, когда я добавляю val.

chornge 17.11.2018 03:22

Я думаю, что переименование сериализованного значения в backend api на «ANSWER» может помочь, но я не уверен, вы можете попробовать.

Sergey 17.11.2018 07:53

да, я считаю, что ты прав. как получилось, что всякий раз, когда я удаляю «val» из сигнатуры метода, ошибка исчезает. почему "val" вызывает проблему?

chornge 19.11.2018 06:00

Я думаю, это потому, что, когда вы используете val, он рассматривается как свойство (без val он считается параметром) и сериализуется Gson с использованием имени свойства как сериализованного имени. В то же время у вас есть такое же сериализованное имя @SerializedName("answer") в вашем базовом классе Answer , поэтому возникает конфликт при сериализации свойств.

Sergey 19.11.2018 07:42

@chornge, я отредактировал свой ответ относительно использования аннотации Expose. Пожалуйста, проверьте, работает ли это для вас.

Sergey 19.11.2018 12:55

по-прежнему вылетает с @Expose, вы можете отредактировать свой ответ, включив объяснение использования 'val'.

chornge 19.11.2018 15:36

Другие вопросы по теме