无法使用Kotlin中的Retrofit TypeAdapter将Gson Doubles舍入为多头

时间:2019-06-25 17:55:24

标签: android json kotlin gson retrofit

好吧,我的API从很早以前就给了我一个流浪245.00000003,当时它应该只发送整数。我想确保只将其解析为245值的Long,并确保后端人员是否再次这样做,我将其四舍五入然后对他们大吼大叫。

我尝试了许多类型的适配器,包括@JsonAdapter注释和registerHierarchyTypeAdapter函数,它们似乎都没有任何作用。我在做什么错了?

@Module
class CoreModule {

    @Provides
    internal fun provideGson(): Gson {
        return GsonBuilder().registerTypeAdapter(Long::class.java, LongTypeAdapter()).create()
    }
}

class LongTypeAdapter : TypeAdapter<Long>() {
    @Throws(IOException::class)
    override fun read(reader: JsonReader): Long? {
        if (reader.peek() === JsonToken.NULL) {
            reader.nextNull()
            return null
        }
        val stringValue = reader.nextString()

        return try {
            stringValue.toLong()
        } catch (e: NumberFormatException) {
            try { stringValue.toDouble().toLong() }
            catch (e: java.lang.NumberFormatException){ 0L }
        }
    }

    @Throws(IOException::class)
    override fun write(out: JsonWriter, value: Long?) {
        if (value == null) {
            out.nullValue()
            return
        }
        out.value(value)
    }
}

我假定代码应该检查我的POJO中的任何Long,并且当需要将其与JSON内容进行匹配时,如果为null,则返回null;如果可以为toLong()'d,则返回Long,如果可以为toDouble().toLong()'d,则为long;否则为0。

POJO:

data class OrdersResponse(
    @SerializedName("error") val error: Boolean,
    @SerializedName("message") val message: String,
    @SerializedName("total") val total: Int,
    @SerializedName("orders") val orders: List<Orders>
) {

    data class Orders(
        @SerializedName("id") val id: Long,
        @SerializedName("status") val status: String,
        @SerializedName("completion_time") val completionTime: Long?,
        @SerializedName("total") val total: Long // This is the dodgy value
    ) {}
}

1 个答案:

答案 0 :(得分:0)

好吧,我弄清楚了,这很混乱,因为有几种选择。 首先,我提供的Gson实施未在转换器工厂用于翻新:

@Provides
@Singleton
fun provideRetrofit(@Named("baseUrlv1") baseUrl: String, okHttpClient: OkHttpClient, gson: Gson): Retrofit {
    return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(LiveDataCallAdapterFactory<Any>())
            .build()
}

第二,我只对此Orders对象中的Long感兴趣,因此,我没有使用类型适配器查看每个Long,而是使用了JsonDeserializermore info here):

@Module
class CoreModule {

    @Provides
    internal fun provideGson(): Gson {
        val gson = GsonBuilder()

        gson.registerTypeAdapter(OrdersResponse.Orders::class.java, OrdersDeserializer())

        return gson.create()
    }
}

class OrdersDeserializer : JsonDeserializer<OrdersResponse.Orders> {
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): OrdersResponse.Orders {
        val jsonObject = json.asJsonObject

        val total = jsonObject.get("total").asNumber.toLong()
        jsonObject.add("total", JsonPrimitive(total))

        return Gson().fromJson(jsonObject, OrdersResponse.Orders::class.java)
    }
}