【发布时间】:2021-01-04 23:42:45
【问题描述】:
我正在尝试使用 Retrofit 对一些已解析的 JSON 执行一些代码,但我遇到了非法状态异常。这是我的改造实例:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.pro.coinbase.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
CoinbaseProAPI coinbaseProAPI = retrofit.create(CoinbaseProAPI.class);
Coinbase Pro API 接口:
@GET("products/{productId}/candles")
Call<ArrayList<HistoricRates>> getHistoricRates(@Header("CB-ACCESS-SIGN") String signature,
@Header("CB-ACCESS-TIMESTAMP") String timeStamp,
@Path("productId") String productId,
@Query("start") String intervalStart,
@Query("end") String intervalEnd,
@Query("granularity") int granularity
);
对服务器的调用请求(这是导致错误的原因):
Call<ArrayList<HistoricRates>> call = coinbaseProAPI.getHistoricRates(signature, timeStamp, productId, intervalStart, intervalEnd, granularity);
try {
//this is being executed inside a for loop; requests are rate limited so consecutive
//iterations must wait
if (i > 0) {
call.wait(1010);
}
//this is the line the debugger doesn't like:
Response<ArrayList<HistoricRates>> response = call.execute();
if (!response.isSuccessful()) {
Message eMsg = errorHandler.obtainMessage();
String e = R.string.error_header + response.toString();
eMsg.what = 2;
eMsg.obj = e;
errorHandler.sendMessage(eMsg);
} else {
ArrayList<HistoricRates> candles = response.body();
int n = 0;
double[][] aCandles = new double[3][3];
for (HistoricRates historicRates : candles) {
aCandles[n][0] = historicRates.getOpen();
aCandles[n][1] = historicRates.getClose();
aCandles[n][2] = historicRates.getVolume();
n++;
}
selectedAsset.setCandles(aCandles);
}
} catch (Exception e) {
Message eMsg = errorHandler.obtainMessage();
eMsg.what = 2;
eMsg.obj = e.getMessage();
errorHandler.sendMessage(eMsg);
e.printStackTrace();
}
最后是 JSON 被解析成的类对象:
public class HistoricRates {
private int time;
private double low;
private double high;
private double open;
private double close;
private double volume;
public double getOpen() {
return open;
}
public double getClose() {
return close;
}
public double getVolume() {
return volume;
}
}
因此,根据我从类似帖子中收集到的信息,发生非法状态异常是因为我试图传递给 Gson 的对象类型不正确。但我不明白这是怎么回事,因为我正在使用 Retrofit; GsonConverterFactory 不应该为我处理这个吗?此外,即使我将此代码包含在 try/catch 块中,它实际上并没有引发异常;它只是默默地失败了。我什至知道非法状态异常的唯一原因是调试控制台。我该如何改进我的错误报告或者还有什么我不理解的地方?
编辑添加: 尝试了 Capps99 的解决方案(在 HistoricRatesList 中添加了访问器方法,因此我可以获得一个迭代器来循环遍历这些值)如下所示:
HistoricRatesList candles = response.body();
Iterator candleIterator = candles.getList().iterator();
int n = 0;
double[][] aCandles = new double[3][3];
while (candleIterator.hasNext()) {
HistoricRates historicRates = (HistoricRates) candleIterator.next();
aCandles[n][0] = historicRates.getOpen();
aCandles[n][1] = historicRates.getClose();
aCandles[n][2] = historicRates.getVolume();
n++;
}
很遗憾,我仍然遇到非法状态例外。应另一位评论者的要求,这是来自服务器的预期 JSON 响应(抱歉,我应该一开始就包括这个):
[
//these are all decimal values except for time; which is an integer value
//representing the UNIX epoch time
[time, low, high, open, close, volume],
[time, low, high, open, close, volume],
...
]
也许问题在于服务器似乎以二维数组的形式返回数据,我没有经验知道如何正确解析。
【问题讨论】:
-
确切的错误信息是什么?
-
你能添加一个你的api返回json数据的例子吗?
-
您使用的 API 是否正确? /candles 的响应是嵌套的 JSONArray。如果您看到 coinbase 文档,您的预期响应与“products/{productId}/stats”匹配
-
retrofit 告诉您响应是 Array,这是正确的。但是,声明的 HistoricRates 的类型是一个对象