Retrofit 2: Get JSON from Response body

AndroidJsonRetrofitRetrofit2

Android Problem Overview


I want to get string json from my api using retrofit 2, I have no problem when using retrofit 1 to get this json but using retrofit 2 returns null for me.

This is what my json looks like

{"id":1,"Username":"admin","Level":"Administrator"}

This is my API

@FormUrlEncoded
@POST("/api/level")
Call<ResponseBody> checkLevel(@Field("id") int id);

This is how my code looks like

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        Api api = retrofit.create(Api.class);
        Call<ResponseBody> call = api.checkLevel(1);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                JsonObject post = new JsonObject().get(response.body().toString()).getAsJsonObject();
                    if (post.get("Level").getAsString().contains("Administrator")) {

                    }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
            }
        });

I'm new to retrofit 2 and using above code, it always make my apps crash because response.body().toString() returns null.

Please guide me on how to get that json string so I can convert it into JsonObject.

Android Solutions


Solution 1 - Android

Use this link to convert your JSON into POJO with select options as selected in image below

enter image description here

You will get a POJO class for your response like this

public class Result {

    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("Username")
    @Expose
    private String username;
    @SerializedName("Level")
    @Expose
    private String level;

    /**
    * 
    * @return
    * The id
    */
    public Integer getId() {
        return id;
    }

    /**
    * 
    * @param id
    * The id
    */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
    * 
    * @return
    * The username
    */
    public String getUsername() {
        return username;
    }

    /**
    * 
    * @param username
    * The Username
    */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
    * 
    * @return
    * The level
    */
    public String getLevel() {
        return level;
    }

    /**
    * 
    * @param level
    * The Level
    */
    public void setLevel(String level) {
        this.level = level;
    }

}

and use interface like this:

@FormUrlEncoded
@POST("/api/level")
Call<Result> checkLevel(@Field("id") int id);

and call like this:

Call<Result> call = api.checkLevel(1);
call.enqueue(new Callback<Result>() {
    @Override
    public void onResponse(Call<Result> call, Response<Result> response) { 
     if(response.isSuccessful()){
        response.body(); // have your all data
        int id =response.body().getId();
        String userName = response.body().getUsername();
        String level = response.body().getLevel();
        }else   Toast.makeText(context,response.errorBody().string(),Toast.LENGTH_SHORT).show(); // this will tell you why your api doesnt work most of time
    
    }

    @Override
    public void onFailure(Call<Result> call, Throwable t) {
     Toast.makeText(context,t.toString(),Toast.LENGTH_SHORT).show(); // ALL NETWORK ERROR HERE
    
    }
});

and use dependencies in Gradle

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.+'

NOTE: The error occurs because you changed your JSON into POJO (by use of addConverterFactory(GsonConverterFactory.create()) in retrofit). If you want response in JSON then remove the addConverterFactory(GsonConverterFactory.create()) from Retrofit. If not then use the above solution

Solution 2 - Android

If you want to get whole response in JSON format, try this:

I have tried a new way to get whole response from server in JSON format without creating any model class. I am not using any model class to get data from server because I don't know what response I will get or it may change according to requirements.

this is JSON response:

{"contacts": [
    {
	    "id": "c200",
	    "name": "sunil",
	    "email": "[email protected]",
	    "address": "xx-xx-xxxx,x - street, x - country",
	    "gender" : "male",
	    "phone": {
		    "mobile": "+91 0000000000",
		    "home": "00 000000",
		    "office": "00 000000"
	    }
    },
    {
	    "id": "c201",
	    "name": "Johnny Depp",
	    "email": "[email protected]",
	    "address": "xx-xx-xxxx,x - street, x - country",
	    "gender" : "male",
	    "phone": {
		    "mobile": "+91 0000000000",
		    "home": "00 000000",
		    "office": "00 000000"
	    }
    },
    .
    .
    .
]}
  1. In your API interface change the parameter

    public interface ApiInterface {
    @POST("/index.php/User/login")//your api link 
    @FormUrlEncoded
    Call<Object> getmovies(@Field("user_email_address") String title,
                    @Field("user_password") String body);
    }
    
  2. in your main activity where you are calling this

    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);
    
    Call call = apiService.getmovies("[email protected]","123456");
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            Log.e("TAG", "response 33: "+new Gson().toJson(response.body()) );
        }
    
        @Override
        public void onFailure(Call call, Throwable t) {
            Log.e("TAG", "onFailure: "+t.toString() );
            // Log error here since request failed
        }
    });
    
  3. after that you can normally get parameter using JSON object and JSON array

Output enter image description here

Solution 3 - Android

use this to get String

String res = response.body().string();

instead of

String res = response.body().toString();

and always keep a check for null before converting responsebody to string

if(response.body() != null){
     //do your stuff   
}

Solution 4 - Android

You can use it like this.

 public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
            if (response.isSuccessful()) {
                try {
                    JSONObject jsonObject = new JSONObject(new Gson().toJson(response.body()));
                    msg = jsonObject.getString("msg");
                    status = jsonObject.getBoolean("status");

                    msg = jsonObject.getString("msg");
                    status = jsonObject.getBoolean("status");
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                Log.e("cvbnop",response.body().toString());
            } else {
                Toast.makeText(MainActivity.this, "Some error occurred...", Toast.LENGTH_LONG).show();
            }
        }

Solution 5 - Android

I found that a combination of the other answers works:

interface ApiInterface {
    @GET("/someurl")
    Call<ResponseBody> getdata()
}

apiService.getdata().enqueue(object : Callback {
    override fun onResponse(call: Call, response: Response) {
        val rawJsonString = response.body()?.string()
    }
})

The important part are that the response type should be ResponseBody and use response.body()?.string() to get the raw string.

https://stackoverflow.com/a/33286112/860488

Solution 6 - Android

add dependency for retrofit2

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

create class for base url

public class ApiClient     
{
public static final String BASE_URL = "base_url";

private static Retrofit retrofit = null;

public static Retrofit getClient() {
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

}

after that create class model to get value

public class ApprovalModel {

@SerializedName("key_parameter")
private String approvalName;
public String getApprovalName() {
    return approvalName;
}
}

create interface class

public interface ApiInterface { 
@GET("append_url")
Call<CompanyDetailsResponse> getCompanyDetails();
}

after that in main class

 if(Connectivity.isConnected(mContext)){
            final ProgressDialog mProgressDialog = new ProgressDialog(mContext);
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.show();

            ApiInterface apiService =
                    ApiClient.getClient().create(ApiInterface.class);
            
            Call<CompanyDetailsResponse> call = apiService.getCompanyDetails();
            call.enqueue(new Callback<CompanyDetailsResponse>() {
                @Override
                public void onResponse(Call<CompanyDetailsResponse>call, Response<CompanyDetailsResponse> response) {
                    mProgressDialog.dismiss();
                    if(response!=null && response.isSuccessful()) {
                        List<CompanyDetails> companyList = response.body().getCompanyDetailsList();

                        if (companyList != null&&companyList.size()>0) {
                            for (int i = 0; i < companyList.size(); i++) {
                                Log.d(TAG, "" + companyList.get(i));
                            }
                         //get values
                        }else{
                            //show alert not get value
                        }
                    }else{
                        //show error message
                        
                    }
                }

                @Override
                public void onFailure(Call<CompanyDetailsResponse>call, Throwable t) {
                    // Log error here since request failed
                    Log.e(TAG, t.toString());
                    mProgressDialog.dismiss();
                }
            });
        }else{
            //network error alert box
                    
        }
             

Solution 7 - Android

A better approach is to let Retrofit generate POJO for you from the json (using gson). First thing is to add .addConverterFactory(GsonConverterFactory.create()) when creating your Retrofit instance. For example, if you had a User java class (such as shown below) that corresponded to your json, then your retrofit api could return Call<User>

class User {
    private String id;
    private String Username;
    private String Level;
    ...
}    

Solution 8 - Android

try {                                                                           
    JSONObject jsonObject = new JSONObject(response.body().string());           
    System.out.println(jsonObject);                                             
} catch (JSONException | IOException e ) {                                      
    e.printStackTrace();                                                        
}

Solution 9 - Android

So, here is the deal:

When making

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

You are passing GsonConverterFactory.create() here. If you do it like this, Gson will automatically convert the json object you get in response to your object <ResponseBody>. Here you can pass all other converters such as Jackson, etc...

Solution 10 - Android

If you don't have idea about What could be the response from the API. Follow the steps to convert the responsebody response value into bytes and print in the String format You can get the entire response printed in the console.

Then you can convert string to JSONObject easily.

      apiService.getFeeds(headerMap, map).enqueue(object : Callback, retrofit2.Callback<ResponseBody> {
            override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
            }

            override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
                val bytes = (response!!.body()!!.bytes())
                Log.d("Retrofit Success : ", ""+ String(bytes))
            }
        })

Solution 11 - Android

you can change your interface with code given below, if you need json String response..

@FormUrlEncoded
@POST("/api/level")
Call<JsonObject> checkLevel(@Field("id") int id);  

and retrofit function with this

Call<JsonObject> call = api.checkLevel(1);
    call.enqueue(new Callback<JsonObject>() {
        @Override
        public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
            Log.d("res", response.body().toString());
        }

        @Override
        public void onFailure(Call<JsonObject> call, Throwable t) {
            Log.d("error",t.getMessage());
        }
    });

Solution 12 - Android

Yo can user like bellow...

  1. Api Interface

    public interface Api {
    
     @POST("app-api/user-login")
     Call<RegistrationResponseModel> doLogin( @Body RegistrationModel userModel);
    
    }
    
  2. ApiService

    public class ApiService {
    
    	Gson gson = new GsonBuilder()
    			.setLenient()
    			.create();
    			
    	public static final String BASE_URL = "your api url";
    
    	Api api = new Retrofit.Builder()
    			.baseUrl(BASE_URL)
    			.addConverterFactory(GsonConverterFactory.create(gson))           
    			.build().create(Api.class);
    
       
    
    	public Call<RegistrationResponseModel> doLogin(RegistrationModel model) {
    		return api.doLogin(model);
    	}
    }
    
  3. Request Model

    public class RegistrationModel {
    	String fullName="";
    	String eamil="";
    	String phone="";
    	String password="";
    	int id = 0;
    	//getter or setter
       }
    
  4. Response model

       public class RegistrationResponseModel {
    		private String outMessage;
    		private String outCode;
    	   //getter setter
    	 }
    
  5. call activity

    	private void doLogin(){
    		
    		ApiService apiService = new ApiService();
    		RegistrationModel model = new RegistrationModel();
    
    		model.setPhone("0192144444");
    		model.setPassword("123");
    		model.setId(3);
    
    		Call<RegistrationResponseModel> call = apiService.doLogin(model);
    		call.enqueue(new Callback<RegistrationResponseModel>() {
    			@Override
    			public void onResponse(Call<RegistrationResponseModel> call, Response<RegistrationResponseModel> response) {
    
    			}
    			
    			@Override
    			public void onFailure(Call<RegistrationResponseModel> call, Throwable t) {
    
    			}
    		});
    	}
    
  6. Don't forget to add bellow library

    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
    
  7. Add tools:replace in manifest file under application.Manifest file look like..

    	<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    	xmlns:tools="http://schemas.android.com/tools"
    	package="your package">
    
    	<uses-permission android:name="android.permission.INTERNET" />
    
    	<application
    		......
    		tools:replace="android:icon" >
    		
    	</application>
    
    </manifest>
    

Enjoy it...

Solution 13 - Android

you can get json response from raw object as you do you get ResponseBody From api

Call<ResponseBody>

and inside call back you can get your json response

json = response.raw().toString();

Solution 14 - Android

use this

response.body().get(0).getUsername().toString();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDirusView Question on Stackoverflow
Solution 1 - AndroidsushildlhView Answer on Stackoverflow
Solution 2 - AndroidSunilView Answer on Stackoverflow
Solution 3 - AndroidRajesh GosemathView Answer on Stackoverflow
Solution 4 - AndroidKrishnaView Answer on Stackoverflow
Solution 5 - AndroidMorten HolmgaardView Answer on Stackoverflow
Solution 6 - AndroidMahesh PanditView Answer on Stackoverflow
Solution 7 - AndroidJohn O'ReillyView Answer on Stackoverflow
Solution 8 - AndroidW. KIJEDIView Answer on Stackoverflow
Solution 9 - AndroidVulovic VukasinView Answer on Stackoverflow
Solution 10 - AndroidSackuriseView Answer on Stackoverflow
Solution 11 - AndroidAbdul HananView Answer on Stackoverflow
Solution 12 - AndroidEnamul HaqueView Answer on Stackoverflow
Solution 13 - AndroidNoah MohamedView Answer on Stackoverflow
Solution 14 - AndroidbakhaView Answer on Stackoverflow