Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POST body JSON using Retrofit

I'm trying to POST a JSONObject using the Retrofit library, but when I see the request at the receiving end, the content-length is 0.

In the RestService interface:

@Headers({
        "Content-type: application/json"
})
@POST("/api/v1/user/controller")
void registerController( 
     @Body JSONObject registrationBundle, 
     @Header("x-company-device-token") String companyDeviceToken, 
     @Header("x-company-device-guid") String companyDeviceGuid, 
     Callback<JSONObject> cb);

And it gets called with,

mRestService.registerController(
    registrationBundle, 
    mApplication.mSession.getCredentials().getDeviceToken(), 
    mApplication.mSession.getCredentials().getDeviceGuid(),
    new Callback<JSONObject>() {
        // ...
    }
)

And I'm certain that the registrationBundle, which is a JSONObject isn't null or empty (the other fields are certainly fine). At the moment the request is made, it logs out as: {"zip":19312,"useAccountZip":false,"controllerName":"mine","registrationCode":"GLD94Q"}.

On the receiving end of the request, I see that the request has Content-type: application/json but has Content-length: 0.

Is there any reason why sending JSON in the body like this isn't working? Am I missing something simple in using Retrofit?

like image 541
adityajones Avatar asked Sep 30 '13 16:09

adityajones


People also ask

How do you post raw whole JSON in the body of a retrofit request?

The Best Answer is The @Body annotation defines a single request body. Since Retrofit uses Gson by default, the FooRequest instances will be serialized as JSON as the sole body of the request. The Gson docs have much more on how object serialization works. And then use an instance of that class similar to #1.

How do you pass body in GET request retrofit on Android?

This means your @GET or @DELETE should not have @Body parameter. You can use query type url or path type url or Query Map to fulfill your need. Else you can use other method annotation.


1 Answers

By default, you don't need to set any headers if you want a JSON request body. Whenever you test Retrofit code, I recommend setting .setLogLevel(RestAdapter.LogLevel.FULL) on your instance of RestAdapter. This will show you the full request headers and body as well as the full response headers and body.

What's occurring is that you are setting the Content-type twice. Then you're passing a JSONObject, which is being passed through the GsonConverter and mangled to look like {"nameValuePairs":YOURJSONSTRING} where YOURJSONSTRING contains your complete, intended JSON output. For obvious reasons, this won't work well with most REST APIs.

You should skip messing with the Content-type header which is already being set to JSON with UTF-8 by default. Also, don't pass a JSONObject to GSON. Pass a Java object for GSON to convert.

Try this if you're using callbacks:

@POST("/api/v1/user/controller")
void registerController(
    @Body MyBundleObject registrationBundle,
    @Header("x-company-device-token") String companyDeviceToken,
    @Header("x-company-device-guid") String companyDeviceGuid,
    Callback<ResponseObject> cb);

I haven't tested this exact syntax.

Synchronous example:

@POST("/api/v1/user/controller")
ResponseObject registerController(
    @Body MyBundleObject registrationBundle,
    @Header("x-company-device-token") String companyDeviceToken,
    @Header("x-company-device-guid") String companyDeviceGuid);
like image 173
colintheshots Avatar answered Sep 20 '22 23:09

colintheshots