问题
I'm trying to send a complex object as a parameter of my request using Retrofit2 and Kotlin. Structure of that object is the following:
{
"id": "..."
"token": "..."
"message": "..."
"list1": [
{ "id": 1, "value": 2 },
{ "id": 2, "value": 5 }
//and so on...
]
"list2": [
{ "id": 10, "value": 16 },
{ "id": 11, "value": 21 }
//and so on...
]
//and so on...
}
The number of list fields is various(could be 2 lists, could be 10) as well as the number of items inside each list. I'm using the following code to achieve that, previously filled my Map with the appropriate values:
@JvmSuppressWildcards
@FormUrlEncoded
@POST("get_data.php")
fun getResponse(
@FieldMap params: Map<String, Any>
): Observable<ResponseModelResult>
For some reason that approach is not working properly and the server just ignoring my params.
I've also tried to send them as @Body
string/object, but it seems like the server accepts only FormUrlEncoded data.
Can someone give me an example how I should send such data as parameter using the @FieldMap
approach?
回答1:
YIf you provide demo url of your api or documentation or something else that would help me find out the problem more specific then I will update my answer according to your api mechanism, now you can try this:
Declare your api interface like this:
@POST("get_data.php")
fun getResponse(@Query("params") params: String): Observable<ResponseModelResult>
Make your complex object like this:
val jsonObject1 = JsonObject().apply {
addProperty("id", 1)
addProperty("value", 1)
}
val jsonObject2 = JsonObject().apply {
addProperty("id", 2)
addProperty("value", 2)
}
val list1 = JsonArray().apply {
add(jsonObject1)
add(jsonObject2)
}
val jsonObject10 = JsonObject().apply {
addProperty("id", 10)
addProperty("value", 16)
}
val jsonObject11 = JsonObject().apply {
addProperty("id", 11)
addProperty("value", 21)
}
val list2 = JsonArray().apply {
add(jsonObject10)
add(jsonObject11)
}
val params = JsonObject().apply {
addProperty("id", "...")
addProperty("token", "...")
addProperty("message", "...")
add("list1", list1)
add("list2", list2)
}.toString()
Here you are ready to go now, call your api passing params
as query parameter like: getResponse(params)
回答2:
instead of @FieldMap you can use @Field like below.
@JvmSuppressWildcards @FormUrlEncoded @POST("get_data.php") fun getResponse( @Field("your key") jsonObject: String ): Observable
Pass the json object as string.
回答3:
Finally, I found a solution. Seems like retrofit can't deal with the <String, Any>
map, so the easiest way would be to send request parameters in a similar way as, for example, in Postman.
val params = mutableMapOf<String, String>()
params["id"] = ...
params["token"] = ...
params["message"] = ...
params["list1[0][id]"] = "${1}"
params["list1[0][value]"] = "${2}"
params["list1[1][id]"] = "${2}"
params["list1[1][value]"] = "${5}"
params["list2[0][id]"] = "${10}"
params["list2[0][value]"] = "${16}"
//and so on
Then, in my ApiService:
@Headers("Content-Type: application/x-www-form-urlencoded")
@FormUrlEncoded
@POST("get_data.php")
fun getResponse(
@FieldMap params: Map<String, String>
): Observable<ResponseModelResult>
Probably, that's not the best approach overall, but at least it works for me.
来源:https://stackoverflow.com/questions/61319947/send-complex-object-using-retrofit2