Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a successful Response body to a specific type using retrofit?

In async mode retrofit calls

public void success(T t, Response rawResponse)

were t is the converted response, and rawResponse is the raw response. This provides you with access to both the raw response and the converted response.

In sync mode you can get either the converted response OR the raw response

converted response

@GET("/users/list")
List<User> userList();

raw response

@GET("/users/list")
Response userList();

The Response object does have a method to get the body

TypedInput  getBody()

and the retrofit api does have a converter class that can convert this to a java object

Object fromBody(TypedInput body,Type type)

But I can not figure out how to get an instance of the Converter object

I might be able to create an instance of the Converter class, but that would require knowledge of the Gson object used to create the RestAdapter, which I may not have access to. Ideally, I would like obtain a reference to the converter object directly the RestAdpater.


Any of the following will answer my question:

  1. Is there a way to get a reference to the default Converter used by retrofit?
  2. Does anyone know how the default Converter is constructed? (there is no default constructor and there are two Constructors public GsonConverter(Gson gson) and public GsonConverter(Gson gson, String charset)
  3. Is there any other way to get both the raw and converted response in sync mode?
like image 527
nPn Avatar asked Oct 24 '14 19:10

nPn


1 Answers

Here's an example of a StringConverter class that implements the Converter found in retrofit. Basically you'll have to override the fromBody() and tell it what you want.

public class StringConverter implements Converter {

    /*
     * In default cases Retrofit calls on GSON which expects a JSON which gives
     * us the following error, com.google.gson.JsonSyntaxException:
     * java.lang.IllegalStateException: Expected BEGIN_OBJECT but was
     * BEGIN_ARRAY at line x column x
     */

    @Override
    public Object fromBody(TypedInput typedInput, Type type)
            throws ConversionException {

        String text = null;
        try {
            text = fromStream(typedInput.in());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return text;
    }

    @Override
    public TypedOutput toBody(Object o) {
        return null;
    }

    // Custom method to convert stream from request to string
    public static String fromStream(InputStream in) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder out = new StringBuilder();
        String newLine = System.getProperty("line.separator");
        String line;
        while ((line = reader.readLine()) != null) {
            out.append(line);
            out.append(newLine);
        }
        return out.toString();
    }
}

Applying this to your request you'll have to do the following:

// initializing Retrofit's rest adapter
RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(ApiConstants.MAIN_URL).setLogLevel(LogLevel.FULL)
        .setConverter(new StringConverter()).build();
like image 58
Rakeeb Rajbhandari Avatar answered Oct 24 '22 22:10

Rakeeb Rajbhandari