首页 > 解决方案 > Retrofit2 奇怪的组合不同大括号前面的request Body

问题描述

我正在使用Retrofit2,但我遇到了这个问题。我为body写了简单的实体:

data class DateRequest(
@JsonAdapter(RetrofitDateSerializer::class)
@SerializedName("date") @Expose val date: OffsetDateTime)

我还为它编写了自定义序列化程序:

class RetrofitDateSerializer : JsonSerializer<OffsetDateTime> {
override fun serialize(
    srcDate: OffsetDateTime?,
    typeOfSrc: Type?,
    context: JsonSerializationContext?
): JsonElement? {
    val formatted = DateTimeUtil.convertFromDateTime(srcDate!!)
    return JsonPrimitive(formatted)
}}

日期时间实用程序:

fun convertFromDateTime(dateTime: OffsetDateTime): String {
    val formatter = formatDateTime()
    return formatter.format(dateTime)
}
fun formatDateTime(): DateTimeFormatter {
    return DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss").withLocale(Locale.US)
}

并在请求正文中以某种方式出现:

)]}'{"date": "2018-12-07 06:00:00"}

这个“ )]}' ”如何附加在请求中我的“日期”json前面?

@POST("changecleaning/{userId}/{cleaningId}/{status}")
fun changeCleaning(
    @Path("userId") userId: Long,
    @Path("cleaningId") cleaningId: Long,
    @Path("status") status: Int,
    @Body date: DateRequest
): Maybe<Status>

我发现只有在JsonWriter在buffer.readByteString()中做了一些魔术之后,它存储了破碎的身体。

GsonRequestBodyConverter

@Override public RequestBody convert(T value) throws IOException {
    Buffer buffer = new Buffer();
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
    JsonWriter jsonWriter = gson.newJsonWriter(writer);
    adapter.write(jsonWriter, value);
    jsonWriter.close();
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());

}

标签: androidkotlinretrofit2rx-java2gson

解决方案


我发现问题出在哪里:

这是我的自定义GsonBuilder

private fun getGsonFactory(): Gson {
        return GsonBuilder()
            .setLenient()
            .serializeSpecialFloatingPointValues()
            .setLongSerializationPolicy(LongSerializationPolicy.DEFAULT)
            .generateNonExecutableJson()
            .enableComplexMapKeySerialization()
            .serializeNulls()
            .setPrettyPrinting()
            .registerTypeAdapter(CleaningProgress::class.java, CleaningProgressDeserializer())
            .create()
    }

下面的代码行,在请求前面添加“ )]}' ”。为什么我将它添加到构建器?我相信有关此方法的官方文档:

通过在生成的 JSON 前面加上一些特殊文本,使输出 JSON 在 Javascript 中不可执行。这可以防止来自第三方站点通过脚本来源的攻击。

.generateNonExecutableJson()

现在我的GsonBuilder看起来像这样:

private fun getGsonFactory(): Gson {
    return GsonBuilder()
        .serializeNulls()
        .registerTypeAdapter(CleaningProgress::class.java, CleaningProgressDeserializer())
        .create()
}

推荐阅读