0

I have a POJO which I want to send to my backend server using Retrofit 2.0.2. It's a simple LoginRequest with loginId and password. Here's the POJO class:

public class LoginRequest {

    private String loginId;
    private String password;

    public void setLoginId(String loginId) {
        this.loginId = loginId;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getLoginId() {
        return loginId;
    }

    public String getPassword() {
        return password;
    }
}

The server is expected to get this data as a raw JSON, it would look like this:

{"loginId":"userLoginId","password":"userPassword"}

The initialization of Retrofit is the following:

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient.build())
            .build();

As you can see, I use GSON to conversion.

My code for the POST-method is this:

@FormUrlEncoded
@Headers(ServiceHandler.REQUEST_HEADER_TITLE + ServiceHandler.REQUEST_HEADER_VALUE_LOGIN)
@POST(ServiceHandler.ENDPOINT)
Call<LoginResponse> getUser(@Field("loginRequest") String loginRequest);

And I start the connection with this line:

Call<LoginResponse> call = service.getUser(loginRequest);

As I know, the converter is used by Retrofit to convert POJO to JSON for request and JSON to POJO for response. So I thought that it will transform my class into the above JSON format.

However, the backend server's response told me that the format of the field is invalid. When I looked at the OkHTTP logger, I've found that:

05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: --> POST http://my.web/page.php http/1.1
05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: Content-Type: application/x-www-form-urlencoded
05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: Content-Length: 79
05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: MyHeader: login
05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: loginRequest=my.package.name.Server.Data.Login.LoginRequest%40189d3779
05-06 06:27:16.569 14103-14434/my.package.name D/OkHttp: --> END POST (79-byte body)

In the 5th row you can see the problem: Retrofit does not serialize my data to JSON before sending the request. All I know about my object that every field inside it is initialized by the setters.

What is the reason? Is my code missing something?

Geryson
  • 719
  • 2
  • 8
  • 25

1 Answers1

0

If you want to directly, you can send the LoginRequest as body.

Call<LoginResponse> getUser(@Body("loginRequest") LoginRequest body);

But if you want to use FormUrlEncoded you have two options: Either you can send all the params & values as separate fields.

Call<LoginResponse> getUser(@Field("loginId") String loginId, @Field("password") String password);

Or you can use HashMap by adding all params and values in it and send it as FieldMap.

Call<LoginResponse> getUser(@FieldMap Map<String, String> fields);


HashMap<String, String> map = new HashMap<String, String>;
map.put("loginId", loginId);
map.put("password", password);
Call<LoginResponse> call = service.getUser(map);

And the answer to your question about

As I know, the converter is used by Retrofit to convert POJO to JSON for request and JSON to POJO for response. So I thought that it will transform my class into the above JSON format.

Yes, the convertor is used to convert POJO to JSON but it only converts POJO (Plain Old Java Objects). Here in your getUser method, loginRequest is a String not LoginRequest object. It will be converted using convertor when LoginRequest is used.

And from the output

loginRequest=my.package.name.Server.Data.Login.LoginRequest%40189d3779

I think you are using toString() method to convert LoginRequest to String. You can try:

new Gson().toJson(loginRequestObject);

It will convert your object to json string but it will not be pretty. You may get something like {\"loginId\":\"userLoginId\",\"password\":\"userPassword\"} instead of {"loginId":"userLoginId","password":"userPassword"} which can be painful for server (Just my assumption).

Rehan
  • 3,270
  • 5
  • 31
  • 30
  • I want to send the data as a field, not a body... That's why I marked the method with @FormUrlEncoded; it's just like a form with textboxes on a webpage, made with Android – Geryson May 06 '16 at 11:44
  • So just for clearing it out; there should be an overridden `toString()` method in my POJO which converts my object with Gson? – Geryson May 07 '16 at 12:17
  • @Geryson That totally depends on the application flow. It's not true in most of the cases, but, in your case, my answer would be *Yes, you need to override `toString()` method in your class* – Rehan May 07 '16 at 14:41
  • Thanks for your answer, but maybe that information could be useful for general purpose... :D Could you talk a little bit more about that "application flow" you mentioned? Is there something what I should change in my project to make that thing work? – Geryson May 08 '16 at 08:44
  • @Geryson It's already in the answer. Re-read it & tell me if something you didn't get or if it's still not like working for you! – Rehan May 08 '16 at 13:14