使用注释在带有嵌套事件的 Moshi 中序列化 Null

问题描述

当从 moshi 调用 toJSON 方法时,我试图添加自定义注释以将模型中的特定值序列化为 null。我有一些基于此 response 的工作,但是当我有嵌套对象时,它对我来说不够用。

@JsonClass(generateAdapter = true)
data class EventWrapper(
    @SerializeNulls val event: Event?,@SerializeNulls val queries: Queries? = null) {

    @JsonClass(generateAdapter = true)
    data class Queries(val stub: String?)

    @JsonClass(generateAdapter = true)
    data class Event(
       val action: String?,val itemAction: String)
}

如果我将 null 传递给 eventqueries,它们将被序列化为:

{
    'event': null,'query': null
}

问题是当事件不为空时,其中有字段我不想序列化,如果它们为空,例如动作。我的首选结果是:

{
    'event': {
        'itemAction': "test" 
    },'query': null
}

但我得到的是:

{
    'event': {
        'action': null,'itemAction': "test" 
    },'query': null
}

以下是基于链接响应的自定义适配器的代码

@Retention(RetentionPolicy.RUNTIME)
 @JsonQualifier
 annotation class SerializeNulls {
     companion object {
         var JSON_ADAPTER_FACTORY: JsonAdapter.Factory = object : JsonAdapter.Factory {

             @RequiresApi(api = Build.VERSION_CODES.P)
             override fun create(type: Type,annotations: Set<Annotation?>,moshi: moshi): JsonAdapter<*>? {
                 val nextAnnotations = Types.nextAnnotations(annotations,SerializeNulls::class.java)

                 return if (nextAnnotations == null) {
                     null
                 } else {
                     moshi.nextAdapter<Any>(this,type,nextAnnotations).serializeNulls()
                 }
        }
    }
}

解决方法

我遇到了同样的问题,我找到的唯一解决方案是制作自定义适配器而不是使用 SerializeNulls 注释。这样,它只会在对象为空时序列化空值,否则使用生成的适配器正常序列化它。

class EventJsonAdapter {
    private val adapter = Moshi.Builder().build().adapter(Event::class.java)

    @ToJson
    fun toJson(writer: JsonWriter,event: Event?) {
        if (event == null) {
            with(writer) {
                serializeNulls = true
                nullValue()
                serializeNulls = false
            }
        } else {
            adapter.toJson(writer,event)
        }
    }
}

为了使生成的适配器工作,不要忘记使用以下注释对 Event 类进行注释:

@JsonClass(generateAdapter = true)

然后可以像这样将自定义适配器添加到 moshi 构建器:

Moshi.Builder().add(EventJsonAdapter()).build()

在我的情况下,我只需要一个特定模型。如果您需要多个,可能不是一个好的解决方案,在这种情况下,注释更实用,但我将其留在这里,因为它可能对其他人有所帮助。