改造2解包信封错误

时间:2018-03-31 15:36:39

标签: java android retrofit2


我使用的API基本上有两个回报:
单个对象:

{
  "data": {Foo}
}

或对象列表:

{
  "data": [
    {Bar},
    {Bar},
    ...
  ]
}

所以,我创建了2个信封类

class Envelope<T> {

    private T data;

    public T getData() {
        return data;
    }
}

class EnvelopeList<T> {

    private List<T> data;

    public List<T> getData() {
        return data;
    }
}

和服务界面

@GET(PATH)
Call<Envelope<Foo>> get();

@GET(PATH_LIST)
Call<EnvelopeList<Bar>> getList();

使用改装2配置

Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create());

一切都很好......

如果我从这样的服务中删除信封

@GET(PATH)
Call<Foo> get();

@GET(PATH_LIST)
Call<List<Bar>> getList();

第一个只返回仍在工作的对象但返回List的对象会返回错误java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

所以,我试图创建一个转换器

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();
    }
}

如果我像这样创建改造版本

Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addConverterFactory(new EnvelopeListConverterFactory());

我仍然得到与以前相同的错误,但如果反转转换器顺序,如

Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(new EnvelopeListConverterFactory())
            .addConverterFactory(GsonConverterFactory.create());

错误更改为java.lang.IllegalArgumentException: Unable to create a converter for class Bar for method Service.getList和返回单个Object的错误,也开始给出相同的错误。

我该怎么做才能使服务返回没有信封的对象?

更新

我认为我在我的问题上传达了错误的想法。问题不在于请求可以返回单个对象或列表。我只是试图通过信封直接获取数据。
我试图这样做http://f2prateek.com/2017/04/21/unwrapping-data-with-retrofit-2/但它无法正常工作

1 个答案:

答案 0 :(得分:0)

我终于找到了如何创建正确的转换器类,而不必在每个请求中都使用信封/包装器。

https://hackernoon.com/retrofit-converter-for-wrapped-responses-8919298a549c