Retrofit无法获取响应报JsonSyntaxException,Logcat可见正常返回
解决Retrofit解析JSON时的JsonSyntaxException(NumberFormatException)问题
我来帮你拆解下这个问题:你看到的JsonSyntaxException本质是数值类型不匹配导致的——接口返回的collection_id值是57213780054,这个数已经远远超出了Java中int类型的最大取值(int最大值是2147483647),Gson在尝试把这个大数值转成int时直接抛出了NumberFormatException,这就是为什么你能通过HTTPLoggingInterceptor看到响应正常,但call.enque()始终进不了onSuccess()的原因。
最直接的解决方案:修改实体类字段类型
既然数值超出了int的范围,那我们把实体类中collection_id的类型改成long就可以了,long的取值范围足够容纳这个数值:
// 你的CollectionListing实体类 public class CollectionListing { // 将int替换为long private long collection_id; private String updated_at; private String body_html; private Object default_product_image; private String handle; private Image image; // 内部Image类保持不变 public static class Image { private String created_at; private String src; // 记得添加getter、setter方法 } // 为所有字段添加getter、setter }
特殊场景:无法修改实体类时的替代方案
如果因为某些限制不能修改实体类,你可以自定义Gson的TypeAdapter来处理这个字段的转换(但不推荐,因为可能会丢失数据):
public class IntToLongAdapter extends TypeAdapter<Integer> { @Override public void write(JsonWriter out, Integer value) throws IOException { out.value(value); } @Override public Integer read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NUMBER) { // 先把数值读成字符串,再尝试转成int String numStr = in.nextString(); try { // 注意:如果数值超过int范围,这里会截断,数据会丢失 return Integer.parseInt(numStr); } catch (NumberFormatException e) { // 可以根据业务需求返回默认值,或者抛出自定义异常 return 0; } } throw new JsonSyntaxException("Expected int but was " + in.peek()); } }
然后在创建Retrofit实例时,把这个自定义Adapter注册到Gson中:
Gson customGson = new GsonBuilder() .registerTypeAdapter(Integer.class, new IntToLongAdapter()) .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(你的BaseUrl) .addConverterFactory(GsonConverterFactory.create(customGson)) .addInterceptor(new HTTPLoggingInterceptor().setLevel(HTTPLoggingInterceptor.Level.BODY)) .build();
总结
优先选择第一种方案,直接修改字段类型为long,这是最安全且不会丢失数据的做法。第二种方案只适合特殊场景,因为大数值转int必然会导致数据截断,可能引发业务问题。
内容的提问来源于stack exchange,提问作者Rakshit Sorathiya
相关产品推荐
相关产品推荐

