17

I have a web query with JSON response as:

{
    "status":true,
    "result":
      {
        "id":"1",
        "name":"ABC 1",
        "email":"info@ABc.dcom",
        "password":"123456",
        "status":false,
        "created":"0000-00-00 00:00:00"
      },
    "message":"Login successfully"
}

I am using the following code for:

@GET("/stockers/login")
public void login(
        @Query("email") String email,
        @Query("password") String password,
        Callback<JSONObject> callback);

In Debugger the query made by the Retrofit library is correct, however I get an empty JSON in response.

ApiManager.getInstance().mUrlManager.login(
        email.getText().toString().trim(),
        password.getText().toString().trim(),
        new Callback<JSONObject>()
        {
            @Override
            public void success(JSONObject jsonObj, Response response)
            {
                mDialog.dismiss();
LisaMM
  • 675
  • 1
  • 16
  • 28
Muhammad Umar
  • 11,391
  • 21
  • 91
  • 193

9 Answers9

22

Simply use JsonElement insted of JSONobject. Like:

@GET("/stockers/login")
Call<JsonElement> getLogin(
    @Query("email") String email,
    @Query("password") String password
);
Leopold Joy
  • 4,524
  • 4
  • 28
  • 37
Shubham Vala
  • 1,024
  • 7
  • 18
13

The answers seam kinda old and for Retrofit 1, if you are using Retrofit 2 and don't want to use a converter you have to use ResponseBody.

@GET("/stockers/login")
public void login(
    @Query("email") String email,
    @Query("password") String password,
    Callback<ResponseBody> callback);

And then in your callback in the onResponse method call string on the body and create a JSONObject from it.

if(response.isSuccessful())
    JSONObject json = new JSONObject(response.body().string());
Stephan
  • 15,704
  • 7
  • 48
  • 63
12

Instead of Callback with JSONObject class, you could use the Retrofit basic callback which use the Response class and then, once you get the response, you had to create the JSONObject from it.

See this: https://stackoverflow.com/a/30870326/2037304

Otherwise you can create your own model class to handle the response.

First the Result class:

public class Result {
    public int id;
    public String name;
    public String email;
    public String password;
    public boolean status;
    public Date created;
}

And then your response class to use with Retrofit

public class MyResponse {
    public boolean status;
    public Result result;
    public String message;
}

Now you can call:

 @GET("/stockers/login") 
 public void login( 
    @Query("email") String email,
    @Query("password") String password,
    Callback<MyResponse> callback);
Community
  • 1
  • 1
Niccolò Passolunghi
  • 5,966
  • 2
  • 25
  • 34
6

You can create custom factory like belowe or copy it from here : https://github.com/marcinOz/Retrofit2JSONConverterFactory

public class JSONConverterFactory extends Converter.Factory {
    public static JSONConverterFactory create() {
        return new JSONConverterFactory();
    }

    private JSONConverterFactory() {
    }

    @Override public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                                    Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        if (type == JSONObject.class
                || type == JSONArray.class) {
            return JSONRequestBodyConverter.INSTANCE;
        }
        return null;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        if (type == JSONObject.class) {
            return JSONResponseBodyConverters.JSONObjectResponseBodyConverter.INSTANCE;
        }
        if (type == JSONArray.class) {
            return JSONResponseBodyConverters.JSONArrayResponseBodyConverter.INSTANCE;
        }
        return null;
    }
}

public class JSONRequestBodyConverter<T> implements Converter<T, RequestBody> {
    static final JSONRequestBodyConverter<Object> INSTANCE = new JSONRequestBodyConverter<>();
    private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain; charset=UTF-8");

    private JSONRequestBodyConverter() {
    }

    @Override public RequestBody convert(T value) throws IOException {
        return RequestBody.create(MEDIA_TYPE, String.valueOf(value));
    }
}

public class JSONResponseBodyConverters {
    private JSONResponseBodyConverters() {}

    static final class JSONObjectResponseBodyConverter implements Converter<ResponseBody, JSONObject> {
        static final JSONObjectResponseBodyConverter INSTANCE = new JSONObjectResponseBodyConverter();

        @Override public JSONObject convert(ResponseBody value) throws IOException {
            try {
                return new JSONObject(value.string());
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    static final class JSONArrayResponseBodyConverter implements Converter<ResponseBody, JSONArray> {
        static final JSONArrayResponseBodyConverter INSTANCE = new JSONArrayResponseBodyConverter();

        @Override public JSONArray convert(ResponseBody value) throws IOException {
            try {
                return new JSONArray(value.string());
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}
oziem
  • 470
  • 6
  • 15
  • 3
    Whoever downvoted this answer, you're supposed to leave a comment explaining why. I think this is a perfectly fine answer. +1. – Vicky Chijwani Jan 31 '17 at 22:26
2

try this instead :

@GET("/stockers/login")
public void login(
        @Query("email") String email,
        @Query("password") String password,
        Callback<Response> callback);  // set the callback generic parameter to Response


ApiManager.getInstance().mUrlManager.login(
        email.getText().toString().trim(),
        password.getText().toString().trim(),
        new Callback<Response>()
        {
            @Override
            public void success(Response response, Response response1)
            {
                String json = response.getBody();
                try {
                    JSONObject jsonObj = new JSONObject(json);
                } catch(JSONException e) {
                }

                alog.dismiss();
Fouad Wahabi
  • 804
  • 7
  • 16
1

Just define the type of the object you want to get as a String as com.google.gson.JsonObject instead of String and call .toString() on that object to get the JSON string itself.

1

After lots of searching i found this solution

Use JsonObject from gson library instead of JSONObject

Check this Check here

0

I`m using this site to create my classes (POJO) from JSON.

http://www.jsonschema2pojo.org/ just be sure to set to JSON insted of JSON Schema and check GSON, because retrofit is using GSON as well for parsing.

your retrofit code looks fine.

narancs
  • 5,234
  • 4
  • 41
  • 60
0

Use JacksonConverterFactory instead of GsonConverterFactory while setting up Retrofit. Now you can directly work with JsonObject responses.

compile 'com.squareup.retrofit2:converter-jackson:2.1.0'

Sahil Patel
  • 684
  • 7
  • 19