我正在使用一个始终返回如下所示的JSON对象的API:
public class ApiResponse<T> {
public boolean success;
public T data;
}
数据字段是一个包含所有有价值信息的JSON对象。当然,对于不同的请求,它们是不同的。所以我的改造界面如下所示:
@GET(...)
Observable<ApiResponse<User>> getUser();
当我想处理响应时,我需要做例如:
response.getData().getUserId();
我真的不需要布尔成功字段,我想省略它,以便我的改造界面看起来像这样:
@GET(...)
Observable<User> getUser();
是否有可能在Gson中这样做?或者可能是一个整洁的Rx函数,它会自动转换它?
编辑: 示例json:
{
"success": true,
"data": {
"id": 22,
"firstname": "Jon",
"lastname": "Snow"
}
}
编辑2: 我已经用改装拦截器做了这个,我手动修改响应体。它有效,但如果您有任何其他建议,请发布它们:)
答案 0 :(得分:6)
正如Than所说,使用拦截器的解决方案并不是那么好。我设法用Rx变压器解决了这个问题。我还添加了自定义api异常,当出现问题时我可以抛出它并在onError中轻松处理它。我认为它更强大。
响应包装器:
public class ApiResponse<T> {
private boolean success;
private T data;
private ApiError error;
}
成功为false时返回错误对象:
public class ApiError {
private int code;
}
成功为假时抛出此异常:
public class ApiException extends RuntimeException {
private final ApiError apiError;
private final transient ApiResponse<?> response;
public ApiException(ApiResponse<?> response) {
this.apiError = response.getError();
this.response = response;
}
public ApiError getApiError() {
return apiError;
}
public ApiResponse<?> getResponse() {
return response;
}
}
和变压器:
protected <T> Observable.Transformer<ApiResponse<T>, T> applySchedulersAndExtractData() {
return observable -> observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(tApiResponse -> {
if (!tApiResponse.isSuccess())
throw new ApiException(tApiResponse);
else
return tApiResponse.getData();
});
}
答案 1 :(得分:1)
据我所知,没有一个简单的解决方案可以达到你想要的效果。通过简单的解决方案,我的意思是比现在更合理的东西。您可以自己反序列化所有数据,您可以使用拦截器剥离数据,但只需使用API就可以实现更多的工作量。
另外,考虑一下如果它发生了变化,并且该项旁边的一些字段apperas和布尔值(例如long
上次更新时间),你将不得不改变一切。
我唯一合理的想法是将Api界面与另一个类包装在一起,并在.map
内调用Observable
将ApiResponse<T>
转换为T
。