user2456977
user2456977

Reputation: 3964

Retrofit not parsing JSONObject

A successful login returns the following JSONObject from a server:

{"success":true,"message":"Sign in success.","response_data":{"user_id":"24", "email_id":"[email protected]", "secret_code": "You did it!"}}

I want to put the response_data info into my User object. I used to do something like this:

String getResponse = jsonObject.getString("response_data");

Gson gson = new GsonBuilder()
        .disableHtmlEscaping()
        .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
        .setPrettyPrinting()
        .serializeNulls()
        .create();

//All the data in the `response_data` is initialized in `User`
User user = gson.fromJson(getResponse, User.class);

Now I tried doing the same in retrofit:

Initializing RestAdapter + Interface:

public class ApiClient {
    private static RetrofitService sRetrofitService;

    public static RetrofitService getRetrofitApiClient() {
        if (sRetrofitService == null) {
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setEndpoint("http://xxx.xxx.xxx.xxx/")
                    .build();

            sRetrofitService = restAdapter.create(RetrofitService.class);
        }

        return sRetrofitService;
    }

    public interface RetrofitService {

        @FormUrlEncoded
        @POST("/login")
        public void login(@Field("email_id") String emailId, @Field ("password") String password, 
                          Callback <User> callback);                                                                    
    }
}

MainActivity:

  ApiClient.getRetrofitApiClient().login(email.getText().toString(), password.getText().toString(),       
      new Callback<User>() {
            @Override
            public void success(User user, Response response) {
                User user1 = user; //null
                Toast.makeText(this, "user is: "+user1.toString(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void failure(RetrofitError error) {
                Toast.makeText(this, "Failed Login", Toast.LENGTH_SHORT).show();
            }
        });

User:

public class User {

    private String userId;
    private String emailId;
    private String code;

    public User() {

    }

    ... getters
    ... setters
}

The Retrofit code in MainActivity works and I get this response in my log:

{"success":true,"message":"Sign in success.","response_data":{"user_id":"24", "email_id":"[email protected]", "secret_code": "You did it!"}}

However it doesn't parse the response_data into my User object.

How do I fix this?

Upvotes: 0

Views: 2296

Answers (3)

Ben Pearson
Ben Pearson

Reputation: 7752

If you do two things it might fix your problem:

  1. Change your FieldNamingPolicy on your GSON Builder to use LOWER_CASE_WITH_UNDERSCORES
  2. Change the scope of your variables in UserResponse and User to public (this might not be required)

Upvotes: 1

cyroxis
cyroxis

Reputation: 3711

You need to create a response object

public class UserResponse {
  private User responseData;
  private String message;
  private boolean success;
}

And change your callback to return a UserResponse

public interface RetrofitService {
    @FormUrlEncoded
    @POST("/login")
    public void login(@Field("email_id") String emailId, @Field ("password") String password, 
                      Callback <UserResponse> callback);                                                                    
}

NOTE: You will also need to create your custom Gson instance and aplly that to the rest adapter.

RestAdapter restAdapter = RestAdapter.Builder()
  .setEndpoint("xxx")
  .setConverter(new GsonConverter(gson))
  .build()

Upvotes: 5

njzk2
njzk2

Reputation: 39397

Firstly,

setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);

You want

setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);

as that's how your fields are named. (e.g. response_data)

Then, your User class does not represent the answer from your service. Create a model class that mimics the structure of your json object. (as suggested by cyroxis).

Finally, the naming of your java members is inconsistent with the naming of your json fields (e.g. secret_code vs code in User). Either fix this, or use @SerializedName to explicitly match a json field to a java field.

Upvotes: 1

Related Questions