无法使用Retrofit 2.6.1成功发送POST请求-JSON Coverter问题

时间:2019-09-21 09:21:50

标签: android kotlin retrofit2 kotlin-coroutines moshi

我正在将新的Retrofit2与暂停的协程一起使用,并且通过GET请求,一切正常。

但是我现在必须实现一个POST请求,但无法使其正常工作

我有一个CURL示例,如下所示:  curl -X POST -H "Content-Type: application/json;charsets: utf-8" -d '{"tx_guapptokenlist_tokenitem":{"tokenchar":"my-token-string","platform":"android"}}' https://www.example-url.com/tokens?type=56427890283537921

这可以正常工作,并返回以下响应:{"errors":false,"success":true}%

这就是我现在在我的Api类中的要求:

    @Headers( "Content-Type: application/json" )
    @POST("/tokens?type=56427890283537921")
    suspend fun sendFirebaseToken(@Body tokenRequest: RequestBody) : Call<TokenResponse>

这是我的TokenResponse类:

@JsonClass(generateAdapter = true)
data class TokenResponse(
    @Json(name="errors")
    val errors: Boolean,
    @Json(name="success")
    val success: Boolean)

和我正在使用的ApiClient类:

object ApiClient {

    private const val BASE_URL = "https://myExampleUrl.com"
    private var retrofit: Retrofit? = null

    var moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
    val client: Retrofit?
        get() {
            if (retrofit == null) {
                retrofit = Retrofit.Builder().baseUrl(
                    BASE_URL
                ).client(getOkHttpClient())
                    .addConverterFactory(MoshiConverterFactory.create())
                    .build()
            }
            return retrofit
        }

    fun getOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder().addInterceptor(getLoggingInterceptor())
            .connectTimeout(120, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS).writeTimeout(90, TimeUnit.SECONDS).build()
    }

    private fun getLoggingInterceptor(): HttpLoggingInterceptor {
        return HttpLoggingInterceptor().setLevel(
            if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.HEADERS
            else HttpLoggingInterceptor.Level.NONE
        )
    }
}

我注意到的第一件事:即使使用@POST批注,如果我的suspend fun没有返回类型,也不会出错,但是okhttp始终会发送GET请求(至少是端点总是收到GET)。不确定是否应该那样吗?

无论如何:我需要返回值,所以我要返回Call<TokenResponse>。 这导致我无法解决的主要问题:如果现在执行我的代码,则此日志将崩溃:

java.lang.IllegalArgumentException: Unable to create converter for     retrofit2.Call<myapp.communication.TokenResponse>
        for method TokenApi.sendToken
        at retrofit2.Utils.methodError(Utils.java:52)

为了尝试解决这个问题,我使用了moshi-kotlin-codegen来生成适当的适配器(因此在数据类中添加了注释),但是没有用。该类已生成,但未使用。我试图将带有var moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()这样的JsonAdapterFactory的Moshi传递给ConverterFactory,但这也不起作用。 试图将生成的适配器手动添加到moshi,但这也行不通。

我也尝试在请求中返回不同的类型。 Retrofit文档指出,如果没有转换器,则只能返回ResponseBody,但结果相同:Retrofit抱怨它没有转换器。返回Call<Void>

我觉得我在这里想念什么吗?谁能帮忙?很高兴提供更多详细信息,请提出要求。

3 个答案:

答案 0 :(得分:1)

认为注释应为:

@JsonClass(generateAdapter = true)
data class TokenResponse(
    @field:Json(name = "errors") val errors: Integer,
    @field:Json(name = "success") val success: Boolean
)

并尝试一次删除suspend关键字,这可能与generateAdapter = true冲突。

答案 1 :(得分:1)

您的请求功能应如下所示。

Args...

由于已将@Headers( "Content-Type: application/json" ) @POST("/tokens?type=56427890283537921") suspend fun sendFirebaseToken(@Body tokenRequest: RequestBody): TokenResponse 标记为暂停,因此您不使用它。

答案 2 :(得分:-1)

我现在开始工作了,这是我学到的:

首先:@Dominic Fischer here是正确的,Call是错误的,并且所有设置正确之后,根本不需要包装结果对象(我注意到了) @Headers注释似乎不是必需的,翻新似乎只是在照顾它)。

第二个最大的问题是我的client类中的ApiClient对象未正确使用。查看新版本:

fun getRetrofitService(): ApiService {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(getOkHttpClient())
            .addConverterFactory(MoshiConverterFactory.create())
            .build().create(ApiService::class.java)
    }

看到现在添加了'create()'步骤,在我在此类之外进行处理之前。在那里,我像这里一样使用Retrofit对象创建服务,但是我不小心通过了ApiClient::class.java。有趣的是,它可以正常编译和运行,但是当然这必须在某个地方搞乱-它无法正确构建JSON适配器。

结果,我将这一步纳入了ApiClient,以防止将来发生此类事故。

如果有人对这个问题+答案有更多建议,对以后的读者更有用,请告诉我!

相关问题