我正在尝试使用Retrofit和Gson解析JSON文件。问题是URL接受参数forceDeviceId
。如果此值设置为-111
,则可以检索正确的文件。默认情况下,此参数设置为-1
并抛出404错误:
我尝试了两种方法:在API网址中对参数进行硬编码并使用查询:
// either hardcoded in the URL
@GET("de/product/productlistajax.json?forceDeviceId=-111")
Call<ProductListParent> loadProductList(
@Query("categoryId") String categoryId,
@Query("sort") String sort,
@Query("lazyLoading") String lazyLoading,
// alternatively use this query
@Query("forceDeviceId") String forceDeviceId
);
但是这两种方法都返回404.所以我想知道我缺少什么才能使它工作(就像在浏览器中一样)。我还认识到,在加载浏览器中的URL后,该参数将被删除immediatley。他们的后端会阻止这件事吗?
以下是我打电话的方法:
@Subscribe
public void getProductListRequest(MMSATServices.ProductListRequest request) {
final MMSATServices.ProductListResponse productListResponse = new MMSATServices.ProductListResponse();
productListResponse.productListParent = new ProductListParent();
Call<ProductListParent> call = liveApi.loadProductList(
request.categoryId, request.sort, request.lazyLoading, request.forceDeviceId);
call.enqueue(new Callback<ProductListParent>() {
@Override
public void onResponse(Call<ProductListParent> call, Response<ProductListParent> response) {
productListResponse.productListParent = response.body();
bus.post(productListResponse);
}
@Override
public void onFailure(Call<ProductListParent> call, Throwable t) {
t.printStackTrace();
}
});
}
这是我收到的错误消息:
Response{protocol=http/1.1, code=404, message=Not Found, url=https://www.mediamarkt.de/de/product/productlistajax.json?categoryId=563612&sort=topseller&lazyLoading=true}
编辑:这是我创建Retrofit对象的方法
private static Retrofit createMMSATService(String baseUrl) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.cookieJar(new CustomCookieJar())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
使用CustomCookieJAr
类:
public class CustomCookieJar implements CookieJar {
private List<Cookie> cookies = new ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
if (cookies != null) {
this.cookies = cookies;
}
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
return cookies;
}
}
答案 0 :(得分:3)
执行此请求时附加2件事,首先获得302响应,然后OkHTTP在302请求提供的新位置执行请求。第二个请求因404响应而失败。我发现302回复标题中包含2个新Cookie:MC_DEVICE_ID
和MC_DEVICE_ID_EXT
。所以我配置了OkHTTP(Retrofit使用的请求引擎)将302响应中收到的cookie发送到第二个请求,它就可以了!
这解释了为什么它在Web浏览器中工作,因为Web浏览器存储返回的cookie并再次发送它以用于第二个请求。默认情况下,OkHTTP没有此机制,您必须在新请求中手动设置302响应中的cookie。
有我的代码:
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private List<Cookie> cookies = new ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
if (cookies != null) {
this.cookies = cookies;
}
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
return cookies;
}
}).build())
.baseUrl("https://www.mediamarkt.de/")
.build()
即使我正在调试,Retrofit / OkHTTP堆栈跟踪也很难解码,但据我所知,网址https://www.mediamarkt.de/de/product/productlistajax.json?categoryId=563612&sort=topseller&lazyLoading=true&forceDeviceId=-111
会返回302
http代码(暂时移动)并在响应头中返回新地址。
问题是标题location
提供的网址不包含查询参数forceDeviceId
。它是来自mediamarkt API的一个错误,我建议你向mediamarkt开发者报告这个错误,并找到另一种方式来发送这个参数(我不能帮助更多,我不明白德国语言)。
第一次调用时返回302的响应:
Response{protocol=http/1.1, code=302, message=Found, url=https://www.mediamarkt.de/de/product/productlistajax.json?forceDeviceId=-111&categoryId=563612&sort=topseller&lazyLoading=true}
OkHTTP通过调用以下内容获取新位置:
String location = userResponse.header("Location");
(见RetryAndFollowUpInterceptor.java:301
)
location
的值为/de/product/productlistajax.json?categoryId=563612&sort=topseller&lazyLoading=true
。如您所见,缺少参数forceDeviceId
:/
答案 1 :(得分:0)
您不需要在GET注释中包含查询参数。下面的代码对我来说很好
@GET("de/product/productlistajax.json")
Call<AppConfigParent> loadAppConfigParent(@Query("forceDeviceId") String forceDeviceId);
答案 2 :(得分:-1)
使用其他参数发送此参数
// either hardcoded in the URL
@GET("de/product/productlistajax.json")
Call<ProductListParent> loadProductList(
@Query("forceDeviceId") String forceDeviceId,
@Query("categoryId") String categoryId,
@Query("sort") String sort,
@Query("lazyLoading") String lazyLoading,
// alternatively use this query
@Query("forceDeviceId") String forceDeviceId
);