Метод модернизации возвращает подстановочный знак

У меня есть ответ API, который предназначен для общего возврата данных для различных действий нашего приложения. Стремясь сделать приложение как можно более универсальным и гибким, мы настроили API для доставки набора URL-адресов, которые можно использовать для создания различных строк в наших действиях. Наш базовый объект выглядит так:

public class BaseApiObject {

    @SerializedName("apiVersion")
    private String apiVersion = null;
    @SerializedName("totalResults")
    private Integer totalResults = null;
}

Наш ответ на активность выглядит так:

public class ActivityApiResponse extends BaseApiObject {
    @SerializedName("results")
    private List<ScreenItem> results = new ArrayList<>();
}

И ScreenItem выглядит так:

public class ScreenItem extends BaseApiObject {
     @SerializedName("apiUrls")
     private List<String> apiUrls = new ArrayList<>() ;
}

Я хотел бы иметь возможность сделать что-то подобное с модификацией:

@GET("{url}")
Call<? extends BaseApiObject> getUrl(@Path("url") String url);

Мы знаем, что каждый сделанный нами запрос будет возвращать BaseApiObject, но мы не уверены, какой тип объекта мы на самом деле вернем — и некоторые из этих URL-адресов вернут список многих различных типов объектов.

Получаем следующую ошибку:

java.lang.IllegalArgumentException: Method return type must not include a type variable or wildcard: retrofit2.Call<? extends com.company.BaseApiObject>

Есть ли способ с помощью Retrofit справиться с этим сценарием или мне нужно вернуть BaseApiObject, а затем использовать пользовательский десериализатор gson, чтобы фактически вернуть правильный тип (ы) объекта?


person Scott    schedule 19.05.2016    source источник


Ответы (1)


В конце концов, мне пришлось создать свой собственный Deserializer. Я взял JsonDeserializationContext, а затем проанализировал свои элементы на основе типа, который был возвращен в ответе json.

Например, предположим, что мой json выглядел так:

{ "shapes": 
  [ 
    {"type": "circle", "radius": 2},
    {"type": "rectangle", "width": 3, "height": 2},
    {"type": "triangle", "sides": [3, 4, 5]}
  ],
  "apiVersion": "0.1.0",
  "totalResults": "3"
}

В моем десериализаторе я бы посмотрел на тип фигур в цикле и сделал бы что-то вроде:

switch(jsonObject.get("type").getAsString()) {
    case "circle":
        return context.deserialize(jsonObject, Circle.class);
        break;

    case "rectangle": 
        return context.deserialize(jsonObject, Rectangle.class);
        break;

    case "triangle":
        return context.deserialize(jsonObject, Triangle.class);
        break;

    default:
        return context.deserialize(jsonObject, Shape.class);
        break; 
}
person Scott    schedule 07.06.2016