Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit 2, same name different data type JSON Parsing

I am trying to parse a JSON response from a server, If there are changes to in the query sent in post method I will get first one as response, if not I will get the second one as response.

1:

{
    "status": 1,
    "data": {
        "firstname": "First Name",
        "lastname": "Last Name",
        "mobilenumber": "1234567894",
        "emailid": "[email protected]",
        "timezone": "Asia/Kolkata"
    },
    "user_id": "",
    "response": "Profile Updated Successfully"
}

2:

{
    "status": 1,
    "data": "No changes to update",
    "user_id": ""
}

As you can see if there are changes the data returns a object, if there are no changes the data returns as string.

I am using this method to get the data and I am using Gson Convertor to map the data.

This is the request interface

@FormUrlEncoded
@POST("pondguard/updateprofile")
Call<UserResponse> getInfoUpdated(@Field("user_id") String user_id,
                                  @Field("firstname") String firstName,
                                  @Field("lastname") String lastName,
                                  @Field("mobilenumber") String mobileNumber,
                                  @Field("emailid") String emailID)

and this is my POJO Class

public class UserResponse implements Parcelable {

    public static final Creator<UserResponse> CREATOR = new Creator<UserResponse>() {
        @Override
        public UserResponse createFromParcel(Parcel in) {
            return new UserResponse(in);
        }

        @Override
        public UserResponse[] newArray(int size) {
            return new UserResponse[size];
        }
    };
    private String status;
    private Data data;
    private String response;
    private String error;

    protected UserResponse(Parcel in) {
        status = in.readString();
        data = in.readParcelable(Data.class.getClassLoader());
        response = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(status);
        dest.writeParcelable(data, flags);
        dest.writeString(response);
    }

    public String getStatus() {
        return status;
    }

    public Data getData() {
        return data;
    }

    public String getResponse() {
        return response;
    }

    public String getError() {
        return error;
    }
}

and finally the Retrofit call I make:

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

UserInfoRequestInterface requestInterface = retrofit.create(UserInfoRequestInterface.class);
Call<UserResponse> call = requestInterface.getInfoUpdated(user_id, firstName, lastName, phoneNumber, email, null, null);
like image 904
Sasi Kanth Avatar asked May 25 '17 03:05

Sasi Kanth


1 Answers

Thank you for your suggestions, but I figured out a working method. Here is how I did it...

First, in my Pojo class, I added a JsonDeserializer, then I check if the "data" is an object or primitive and depending on that I set the respective fields.

public class UserResponse  {

    @SerializedName("status")
    private String status;
    @SerializedName("data")
    private Object mData;
    @SerializedName("response")
    private String response;
    @SerializedName("error")
    private String error;

    private String message;
    private String firstname;
    private String lastname;
    private String mobilenumber;
    private String emailid;
    private String timezone;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getMobilenumber() {
        return mobilenumber;
    }

    public void setMobilenumber(String mobilenumber) {
        this.mobilenumber = mobilenumber;
    }

    public String getEmailid() {
        return emailid;
    }

    public void setEmailid(String emailid) {
        this.emailid = emailid;
    }

    public String getTimezone() {
        return timezone;
    }

    public void setTimezone(String timezone) {
        this.timezone = timezone;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Object getmData() {
        return mData;
    }

    public String getResponse() {
        return response;
    }

    public String getError() {
        return error;
    }

    public static class DataStateDeserializer implements JsonDeserializer<UserResponse> {

        @Override
        public UserResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            UserResponse userResponse = new Gson().fromJson(json, UserResponse.class);
            JsonObject jsonObject = json.getAsJsonObject();

            if (jsonObject.has("data")) {
                JsonElement elem = jsonObject.get("data");
                if (elem != null && !elem.isJsonNull()) {                     
                    if(elem.isJsonPrimitive()){                            
                        userResponse.setMessage(elem.getAsString());
                    }else{

                        userResponse.setFirstname(elem.getAsJsonObject().get("firstname").getAsString());
                        userResponse.setLastname(elem.getAsJsonObject().get("lastname").getAsString());
                        userResponse.setMobilenumber(elem.getAsJsonObject().get("mobilenumber").getAsString());
                        userResponse.setEmailid(elem.getAsJsonObject().get("emailid").getAsString());
                        userResponse.setTimezone(elem.getAsJsonObject().get("timezone").getAsString());
                    }
                }
            }
            return userResponse ;
        }
    }
}

and I attach the json deserializer to the type adapter of GSON Builder and give it to create method of GsonConvertor in Retrofit like this

Gson gson = new GsonBuilder()
                 .registerTypeAdapter(UserResponse.class, new UserResponse.DataStateDeserializer())
                .create();

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ConstantUtils.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

UserInfoRequestInterface requestInterface = retrofit.create(UserInfoRequestInterface.class);
        Call<UserResponse> call = requestInterface.getInfoUpdated(user_id, firstName, lastName, phoneNumber, email, null, null);

Then all I have to do is check if message is null or not and perform my required action accordingly.

like image 101
Sasi Kanth Avatar answered Nov 18 '22 03:11

Sasi Kanth