I am using an API that has basically 2 returns:
A single object:
{
"data": {Foo}
}
Or a list of objects:
{
"data": [
{Bar},
{Bar},
...
]
}
So, I have created 2 envelope class
class Envelope<T> {
private T data;
public T getData() {
return data;
}
}
class EnvelopeList<T> {
private List<T> data;
public List<T> getData() {
return data;
}
}
and the service interface
@GET(PATH)
Call<Envelope<Foo>> get();
@GET(PATH_LIST)
Call<EnvelopeList<Bar>> getList();
Using the retrofit 2 config
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
everything is working fine...
If I remove the envelope from service like this
@GET(PATH)
Call<Foo> get();
@GET(PATH_LIST)
Call<List<Bar>> getList();
the first that return only an object still working but the one that returns a List gives the error java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
So, I tried to create a converter
public class EnvelopeListConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
final Type type,
Annotation[] annotations,
Retrofit retrofit) {
Type envelopeType = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[]{type};
}
@Override
public Type getRawType() {
return null;
}
@Override
public Type getOwnerType() {
return EnvelopeList.class;
}
};
Converter<ResponseBody, EnvelopeList> delegate =
retrofit.nextResponseBodyConverter(this, envelopeType, annotations);
return new EnvelopeListConverter(delegate);
}
}
public class EnvelopeListConverter<T> implements Converter<ResponseBody, List<T>> {
final Converter<ResponseBody, EnvelopeList<T>> delegate;
EnvelopeListConverter(Converter<ResponseBody, EnvelopeList<T>> delegate) {
this.delegate = delegate;
}
@Override
public List<T> convert(ResponseBody responseBody) throws IOException {
EnvelopeList<T> envelope = delegate.convert(responseBody);
return envelope.getData();
}
}
and if I create the retrofit build like this
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(new EnvelopeListConverterFactory());
I still get the same error as before, but if invert the converter order like
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(new EnvelopeListConverterFactory())
.addConverterFactory(GsonConverterFactory.create());
the error change to java.lang.IllegalArgumentException: Unable to create a converter for class Bar for method Service.getList
and the one that returns a single Object, start to give the same error too.
What can I do to make the service return the Objects without the envelope?
Update
I think I passed the wrong idea on my question. The problem is not that the request can return a single object or a list. I just trying to pass thru the envelope and get the data directly.
I trying to do this http://f2prateek.com/2017/04/21/unwrapping-data-with-retrofit-2/ but it is not working