如何使用Moshi和翻新将空对象转换为null?

时间:2019-05-14 17:41:14

标签: android retrofit2 moshi

我正在Kotlin中使用Retrofit2 + Moshi连接到服务器。

所有响应均包装有 result 属性。我创建了如下的通用数据类

@JsonClass(generateAdapter = true)
data class CommonResponse<T>(val result: T?)

例如,如果result属性不为空,则可以正常工作

{
    "result": {
        "bar": 1
    }
}

具有数据类Foo并将泛型与Foo一起使用

data class Foo(val bar: Int)

interface {

    @Path("/foo")
    fun getFoo(): CommonResponse<Foo>
}

但是,如果 result 属性为空,则如下所示:

{
  "result": {}
}

由于bar不能为null,我得到了JsonDataException。

对于result属性为空的情况,是否可以将其视为null?

到目前为止,我所做的就是捕获JsonDataException异常并为这些情况返回null,但是由于没有数据的结果是有效的响应,因此我对这种解决方案不满意。另外,我将无法在没有结果的响应或无效的响应之间进行区分。

有什么主意吗?

注意:我无法修改服务器响应。

2 个答案:

答案 0 :(得分:0)

  

对于result属性为空的情况,是否可以将其视为null?

是的,您需要使属性栏可为空,因为Int?例外,并为该属性添加默认值,这样,如果不存在该属性,则可以将其设置为null。因此,将data class Foo(val bar: Int)更改为data class Foo(val bar: Int? = null)

这会将以下JSON的bar设置为null:

{
    "result": {
        "bar": null
    }
}

...和

{
    "result": {}
}

答案 1 :(得分:0)

如果JSON为空,要将结果设置为null,则需要为CommonResponse创建自己的自定义适配器。因此,首先您不需要为CommonResponse生成适配器:

data class CommonResponse<T>(val result: T?)
data class Foo(val bar: Int)

...然后您需要为Foo类型的CommonResponse创建自定义适配器:

class CommonResponseAdapterFoo {

    @FromJson
    fun fromJson(reader: JsonReader): CommonResponse<Foo>{
        var fooObj: Foo? = null

        while (reader.hasNext()) {
            reader.beginObject()
            if (reader.nextName() == "result") {
                reader.beginObject()
                if (reader.hasNext()) {
                    if (reader.nextName() == "bar") {
                        val barValue = reader.nextInt()
                        fooObj = Foo(barValue)
                    }
                }
                reader.endObject()

            }
            reader.endObject()
        }

        return CommonResponse(fooObj)
    }
}

...然后您需要将此自定义适配器添加到您的moshi实例:

val moshi = Moshi.Builder().add(CommonResponseAdapterFoo()).build()

如果要在CommonResponse中包装多个类型,则可能必须创建多个自定义适配器来容纳所有不同的类型