java - Retrofit 2 展开信封错误

标签 java android retrofit2


我使用的 API 基本上有 2 个返回值:
单个对象:

{
  "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;
    }
}

和服务接口(interface)

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

第一个仅返回一个仍在工作的对象但返回列表的对象给出错误 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 以及返回单个对象的转换器,也开始出现相同的错误。

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

更新

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

最佳答案

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

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

关于java - Retrofit 2 展开信封错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49589463/

相关文章:

java - Android:启动前台不会正确显示通知

android - 单击通知操作时如何取消改造 2 请求?

Android - 如何在微调器上获取所选项目的另一个值

android - Retrofit 2 with 协程调用适配器工厂取消请求

java - 属性 : system vs. 部署描述符与属性文件的优先级

java - 在 Java 桌面应用程序中实现 'Send Feedback' 功能

java - 尝试通过 Intellij IDEA 部署 tomcat 服务器并出现奇怪的 missing server.xml 错误

java - Android-从另一个 onButtonClick Activity 将项目添加到 ListView

java - spring jdbc 模板和最好用的一个

android - MPChartAndroid 在 Kotlin 错误空对象引用中的 Fragment tabslider 上崩溃