Search code examples
javaandroidapiretrofitviewmodel

How to get inner indexed object from json response in android (java) which use retrofit for rest api calls


I am facing issue for fetching object from inner object of api response. My api response format is given below

{
    status: true,
    message: success,
    result: {
        name: demo,
        url: mysiet.com
    }
}

I have created two model classes as given below

Project.java

public class Project {

    @SerializedName("result")
    @Expose
    private ProjectData result;

    @SerializedName("message")
    @Expose
    private String message;

    @SerializedName("status")
    @Expose
    private boolean status;

    //constructor, setter and getter functions I am skipping 

}

ProjectData.java

public class ProjectData { 

    @SerializedName("name")
    @Expose
    private String name;

    @SerializedName("url")
    @Expose
    private String url;

    //constructor, setter and getter functions I am skipping 

}

In my viewmodel I have send the api request to server as follows

final LiveData<Resource<Project>> source = LiveDataReactiveStreams.fromPublisher(
        dashboardApi.getProjectData(
                  "Bearer "+this.authCode,
                 "applicaion/json"
        )
        .onErrorReturn(new Function<Throwable, Project>() {
            @Override
            public Project apply(Throwable throwable) throws Exception {
                Project projects = new Project();
                projects.setStatus(false);
                Log.d( TAG , "projectResource error ");
                return projects;
            }
        })
        .map(new Function<Project, Resource<Project>>() {
            @Override
            public Resource<Project> apply(Project project) throws Exception {
                Log.d( TAG , "projectResource full Status "+project.getStatus()); // This retruns correctly
                Log.d( TAG , "projectResource full Obj "+project.getResult()); // This is not null hence object works
                Log.d( TAG , "projectResource full Obj "+project.getResult().getName()); // This cause error
                //The above line cause error
                if(project.getStatus() == false){
                    return Resource.error("projectResource Could not authenticate", null);
                }
                return Resource.success(project);
            }
        }).subscribeOn(Schedulers.io())
);

Request is send as given below

@POST("myendpoint")
Flowable<Project> getProjectData(
        @Header("Authorization") String token,
        @Header("Accept") String accept
);

Error I got is given below

The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.AbstractMethodError: abstract method "java.lang.String com.myapppackage.f.c.a()"


Solution

  • I am posting an answer that I used to get values of inner index json object. I am expecting any other solutions too as answers

    In model I have created result as Object datatype as follows

    @SerializedName("result")
    @Expose
    private Object result;
    

    In the view model Map function I did the following to get inner json object

    map(new Function<Project, Resource<Project>>()  {
        @Override
        public Resource<Project> apply(Project project) throws Exception {
            Gson gson = new Gson();
            String projectData = gson.toJson(project.getResult());
            // The above code return result index as string {"name": "demo", "url": "mysiet.com"}
            try{
    
                JSONObject projectObj = new JSONObject( projectData );// get inner json index as object
                project.setName(projectObj.getString("name"));
                project.setUrl(projectObj.getString("url"));
    
    
            } catch (JSONException e) {
                Log.d( TAG , "JSONException : "+e.getMessage());
            }
    
            if(project.getStatus() == false){
                return Resource.error(project.getMessage(), null);
            }
    
            return Resource.success(project);
        }
    })
    

    I guess there will be other solutions too , Please be feel free to post answers