【问题标题】:Moshi serialize generic classes "Failed to find the generated JsonAdapter constructor..."Moshi 序列化泛型类“找不到生成的 JsonAdapter 构造函数...”
【发布时间】:2021-09-30 14:00:09
【问题描述】:

我有以下类层次结构Github Sample

interface OptionV2 {
    val id: String
}

@JsonClass(generateAdapter = true)
class ImageSelectionOption(
    override val id: String,

    value: String,

    @Json(name = "active_image")
    val image: String?,
): OptionV2

@JsonClass(generateAdapter = true)
class QuestionResponse<T> (
    override val id: String,
    val answer: T?,
): OptionV2

接下来的测试

        val childOptions = listOf(ImageSelectionOption(value = "dummy", id = "dummy", image = "dummy"))
        val childResponse = QuestionResponse<List<OptionV2>>(answer = childOptions, id = "child_qid")

        val parentOptions = listOf(childResponse)
        val parentResponse = QuestionResponse<Any>(answer = parentOptions, id = "parent_qid")

        val moshi = Moshi.Builder().add(OptionV2MoshiAdapter.OptionAdapterFactory).build()

        val type = Types.newParameterizedType(QuestionResponse::class.java, Any::class.java)
        moshi.adapter<QuestionResponse<Any>>(type).toJson(parentResponse)

我实际上是在尝试反序列化 QuestionResponse&lt;List&lt;QuestionResponse&lt;List&lt;Option&gt;&gt;&gt;&gt; 类型。这失败并出现以下错误

找不到为“class dev.abhishekbansal.moshilistinheritance.QuestionResponse”生成的 JsonAdapter 构造函数。可疑的是,该类型没有参数化,但目标类“dev.abhishekbansal.moshilistinheritance.QuestionResponseJsonAdapter”是通用的。考虑使用 Types#newParameterizedType() 来定义这些缺失的类型变量。

如果需要,我希望能够为此编写一个自定义适配器。因为我需要能够在改造方案中反序列化它。

这里是more complete Github Sample

更新

终于用这个搞定了

        // List<Option>
        val listType = Types.newParameterizedType(List::class.java, OptionV2::class.java)
        // QuestionResponse<List<Option>>
        val qr1 = Types.newParameterizedType(QuestionResponse::class.java, listType)
        // List<QuestionResponse<List<Option>>>
        val listType2 = Types.newParameterizedType(List::class.java, qr1)
        // QuestionResponse<List<QuestionResponse<List<Option>>>>
        val finalType = Types.newParameterizedType(QuestionResponse::class.java, listType2)
        println(moshi.adapter<QuestionResponse<Any>>(finalType).toJson(parentResponse))

我仍然对如何为此编写自定义适配器感到困惑,该适配器可以提供给Moshi 提供给Retrofit 的实例。这样它就可以在运行中被序列化。

【问题讨论】:

    标签: android json serialization moshi


    【解决方案1】:

    这是对我有用的自定义适配器。我对此有一些疑问,但它确实有效。

    class QuestionResponseAdapter<T>(val elementAdapter: JsonAdapter<T>) : JsonAdapter<T>() {
    
        override fun fromJson(reader: JsonReader): T? {
            return elementAdapter.fromJson(reader)
        }
    
        override fun toJson(writer: JsonWriter, value: T?) {
            elementAdapter.toJson(writer, value)
        }
    
        object QuestionResponseAdapterFactory : Factory {
    
            override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
                if (!annotations.isEmpty()) {
                    return null // Annotations? This factory doesn't apply.
                }
    
                if (type !== QuestionResponse::class.java) {
                    return null // Not a QuestionResponse This factory doesn't apply.
                }
    
                // Handle Type erasure at runtime, this class does not need adapter with single level of generic though
                val parameterizedType = Types.newParameterizedType(type, Any::class.java)
                val elementAdapter: JsonAdapter<Any> = moshi.adapter(parameterizedType)
    
                return QuestionResponseAdapter(elementAdapter).nullSafe()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 1970-01-01
      • 2022-01-26
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 2018-12-22
      • 1970-01-01
      相关资源
      最近更新 更多