Retrofit: Kotlin & @Body

Created on 20 May 2016  路  15Comments  路  Source: square/retrofit

I have a query

@PUT("/api/v3/{storeId}/categories/{categoryId}")
fun update(@Path("storeId") storeId: Int, @Path("categoryId") categoryId: Int?, @Query("token") token: String, @Body category: Map<String, Any>): Observable<OperationResultUpdated>

When I call it by

update(storeId, category.id, token, mapOf("name" to category2))

I receive an error

java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?> (parameter #4)

How can I solve that problem?

Most helpful comment

You can still use Map, just suppress its wildcardness with @JvmSuppressWildcards

@PUT("/api/v3/{storeId}/categories/{categoryId}")
fun update(@Path("storeId") storeId: Int, @Path("categoryId") categoryId: Int?, @Query("token") token: String, @Body category: Map<String, @JvmSuppressWildcards Any>): Observable<OperationResultUpdated>

All 15 comments

@Body category: RequestBody

Here's an example on creating the RequestBody

val requestBody = RequestBody.create(MediaType.parse("text/plain"), getRequestBody())

Where in this example getRequestBody() basically returns a String, but I think this is enough for you to get the gist.

Just use Object for the value type?

i forced to roll back retrofit interface back to java. Object didn't help

I think it's happening because the Map declaration is public interface Map<K, out V> and the out word makes the value type generic. You can try to use MutableMap or HashMap instead.

You can still use Map, just suppress its wildcardness with @JvmSuppressWildcards

@PUT("/api/v3/{storeId}/categories/{categoryId}")
fun update(@Path("storeId") storeId: Int, @Path("categoryId") categoryId: Int?, @Query("token") token: String, @Body category: Map<String, @JvmSuppressWildcards Any>): Observable<OperationResultUpdated>

I use @Body in @POST method with kotlin, my app always crash, however it work well with other method like @GET, @DELETE ...

@hzsweers tks a lot, solve my problem.

Hi @PhanPirang Use @FormUrlEncoded for Post method. I think your problem will get solve

Thanks @hzsweers. You save my Day :). I struggled a lot to Resolve this problem. Thanks Buddy

I had a List<Map<String, String>>

That became: @Field("exercises[]") exercises: List<@JvmSuppressWildcards Map<String, @JvmSuppressWildcards String>>

Ugly but works :/ Thanks a lot @hzsweers

@hzsweers Thanks Buddy

This code works:
fun getSomethings(@Body body: HashMap<String, Any>): Observable<List<Something>>
This code does not work:
fun getSomethings(@Body body: Map<String, Any>): Observable<List<Something>>

I went with this:

typealias StringAnyMap = Map<String, @JvmSuppressWildcards Any>

update Map to MutableMap

(FYI @vpratfr)

Annotating the whole interface works as well:

@JvmSuppressWildcards
interface MyRetrofitApi {
    ...
}

And will avoid having parameters type like: List<@JvmSuppressWildcards Map<String, @JvmSuppressWildcards String>>

Was this page helpful?
0 / 5 - 0 ratings