【问题标题】:Gson serialization error with val in kotlinkotlin中带有val的Gson序列化错误
【发布时间】:2019-04-19 23:34:09
【问题描述】:

我正在使用 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 answerAnswerSummary(val answer: Answer) 中的val answer 重命名为其他名称。
  • 我提到当我使用不同的变量名时我会避免崩溃:class AnswerSummary(val ans: Answer),我在问发生了什么:为什么我必须删除'val ' or 改变变量名?
  • 因为 Retrofit 无法为类 com.name.app.model.response.AnswerResponse 创建转换器,因为 AnswerSummary 声明了多个名为 answer 的 JSON 字段。你会在改造的地方做什么? :)

标签: android kotlin serialization gson retrofit2


【解决方案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 使用属性名称作为序列化名称进行序列化。同时,您的基类 Answer 中有相同的序列化名称 @SerializedName("answer"),因此在序列化属性时会发生冲突。

【讨论】:

  • 为什么我必须重命名变量?是因为@SerializedName 也是“答案”吗?
  • 是的,错误“com.name.app.model.pojo.AnswerSummary 类声明多个名为 answer 的 JSON 字段”表示有多个字段名为 answer
  • 使用@Expose 注解仍然会导致应用程序崩溃。如果序列化的字段值(在后端 api 中)更改为 "ANSWER" 而不是 "answer",你知道这是否会避免崩溃吗?我知道我可以重命名参数,但答案比ansanswerParam 更易读。我的备份选项是删除“val”,因为只有在我添加“val”时才会发生崩溃。
  • 我认为将后端 api 中的序列化值重命名为“ANSWER”可能会有所帮助,但我不确定,你可以试试。
  • 是的,我相信你是对的。每当我从方法签名中删除“val”时,错误就会消失。为什么“val”会出现问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多