kotlin使用retrofit2解析结果,不赋值默认值的问题

首先感谢这位老哥的方法

我定义了data class的属性为val 且都不为null,都有默认值,这样子避免UI页面显示出问题,而且拿取属性的时候,不需要判空,使用也方便。

按道理,json解析的时候,遇到value为null的时候,应该使用默认值,但是呢,gson却给赋值了null进去,是的,是null,明明定义这个属性不为null且有默认值,然后ide提示你这个属性又一定不为null,所以,当请求结果有某个属性是null的时候,直接使用的话,就会崩溃。

你又不可能每个属性在使用的时候都要判空,或者把属性声明成可为null的?,这样工作量有点大,也不符合自己的预期。

网上大佬解释是,拿不到class的无参构造函数,会使用不安全的反射方式创建对象,再赋值,在解析的时候,遇到字段是null,直接赋值null。然后,我把data class改成class也是一样不可行,把构造函数参数全挪成全局属性也不行。

然后看了老哥的方法,试了一下,没有崩溃了,好像是解决了。

fun gsonNullToDefault(): Gson = GsonBuilder()
    .registerTypeAdapterFactory(GsonDefaultAdapterFactory())
    .create()

class GsonDefaultAdapterFactory: TypeAdapterFactory {
    override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
        if (type.type == String::class.java) {
            return createStringAdapter()
        }
        if (type.rawType == List::class.java || type.rawType == Collection::class.java) {
            return createCollectionAdapter(type, gson)
        }
        return null
    }
    /**
     * null替换成空List
     */
    private fun <T : Any> createCollectionAdapter(
        type: TypeToken<T>,
        gson: Gson
    ): TypeAdapter<T>? {
        val rawType = type.rawType
        if (!Collection::class.java.isAssignableFrom(rawType)) {
            return null
        }
        val elementType: Type = `$Gson$Types`.getCollectionElementType(type.type, rawType)
        val elementTypeAdapter: TypeAdapter<Any> =
            gson.getAdapter(TypeToken.get(elementType)) as TypeAdapter<Any>
        return object : TypeAdapter<Collection<Any>>() {
            override fun write(writer: JsonWriter, value: Collection<Any>?) {
                writer.beginArray()
                value?.forEach {
                    elementTypeAdapter.write(writer, it)
                }
                writer.endArray()
            }
            override fun read(reader: JsonReader): Collection<Any> {
                val list = mutableListOf<Any>()
                // null替换为空list
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return list
                }
                reader.beginArray()
                while (reader.hasNext()) {
                    val element = elementTypeAdapter.read(reader)
                    list.add(element)
                }
                reader.endArray()
                return list
            }
        } as TypeAdapter<T>
    }
    /**
     * null 替换成空字符串
     */
    private fun <T : Any> createStringAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<String>() {
            override fun write(writer: JsonWriter, value: String?) {
                if (value == null) {
                    writer.value("")
                } else {
                    writer.value(value)
                }
            }
            override fun read(reader: JsonReader): String {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return ""
                }
                return reader.nextString()
            }
        } as TypeAdapter<T>
    }
}

然后在retrofit解析拦截器里,稍微改一下即可

.addConverterFactory(GsonConverterFactory.create(gsonNullToDefault()))

在使用kotlin的时候,最好使用这个gsonNullToDefault()解析json

再次感谢这个老哥拯救了我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值