好吧,我的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
) {}
}
答案 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,而是使用了JsonDeserializer
(more 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)
}
}