从Retrofit响应解析JSONArray失败,请求协助排查问题
解析Retrofit响应时JSONArray解析失败问题排查与修复
问题背景
我在解析Retrofit返回的JSON响应时遇到了JSONArray解析失败的问题,以下是相关信息:
服务器返回的JSON数据:
{ "code": "200", "contentType": "Json", "data": [{ "createdon": "2017-12-2", "fname": "abhay", "mobileno": "1234567890", "userid": 1234, "profileimagepath": null }], "maxjsonlength": 1233, "message": "Success", "status": true }
对应的Model类:
// 主Model类 public class Example { @SerializedName("code") @Expose private String code; @SerializedName("contentType") @Expose private String contentType; @SerializedName("data") @Expose private List<Datum> data = null; @SerializedName("maxjsonlength") @Expose private Integer maxjsonlength; @SerializedName("message") @Expose private String message; @SerializedName("status") @Expose private Boolean status; // getter和setter方法 } // Data数组项的Model类 public class Datum { @SerializedName("createdon") @Expose private String createdon; @SerializedName("fname") @Expose private String fname; @SerializedName("mobileno") @Expose private String mobileno; @SerializedName("userid") @Expose private Integer userid; @SerializedName("profileimagepath") @Expose private Object profileimagepath; // getter和setter方法 }
Retrofit接口与调用代码:
// 接口定义 @Headers({ "Content-Type:application/json", "Bearer:mlm_token" }) @GET("api/v1.0/****/TestApi/{id}") Call<Example> getTestJson(@Query("id") int userId); // 调用代码 DrawerMethods msgInterface = (DrawerMethods) NetworkModule.getInstance().createClassInstance(DrawerMethods.class); Call<Example> mLoginCall = msgInterface.getTestJson(userId); mLoginCall.enqueue(new Callback<Example>() { @Override public void onResponse(Call<Example> call, Response<Example> response) { // 响应处理逻辑 } @Override public void onFailure(Call<Example> call, Throwable t) { // 失败处理逻辑 } });
核心问题排查与修复
1. 路径参数与查询参数误用(最可能的原因)
你的Retrofit接口中,@GET路径里包含{id}路径参数,但你却用了@Query("id")来传递参数,这会导致请求的URL完全不符合服务器预期:
- 错误的URL示例:
api/v1.0/****/TestApi/{id}?id=123({id}会被原样保留,同时额外添加查询参数id=123) - 服务器期望的URL应该是:
api/v1.0/****/TestApi/123
修复方法:将@Query("id")替换为@Path("id"),让Retrofit正确替换路径中的占位符:
@Headers({ "Content-Type:application/json", "Bearer:mlm_token" }) @GET("api/v1.0/****/TestApi/{id}") Call<Example> getTestJson(@Path("id") int userId);
2. 其他可能的排查点
如果修复上述问题后仍无法解析,建议检查以下内容:
- 确认Retrofit已配置Gson转换器:在构建Retrofit实例时,必须添加Gson转换器工厂,否则无法自动完成JSON到Model的映射:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) // 这一行必须存在 .build(); - 检查服务器返回的实际响应:通过OkHttp的
LoggingInterceptor打印完整的请求和响应内容,确认服务器返回的JSON结构与你预期的一致——比如是否存在data字段为非数组(单个对象或null)的特殊情况。 - 兼容
data字段的非数组场景:如果服务器在某些场景下返回data为单个对象或null,可以给Gson配置自定义TypeAdapter来兼容:
然后在Retrofit构建时使用这个自定义Gson实例:Gson gson = new GsonBuilder() .registerTypeAdapter(new TypeToken<List<Datum>>(){}.getType(), new TypeAdapter<List<Datum>>() { @Override public void write(JsonWriter out, List<Datum> value) throws IOException { // 按需实现写入逻辑 } @Override public List<Datum> read(JsonReader in) throws IOException { List<Datum> list = new ArrayList<>(); if (in.peek() == JsonToken.BEGIN_OBJECT) { // 单个对象转为列表 Datum datum = new Gson().fromJson(in, Datum.class); list.add(datum); } else if (in.peek() == JsonToken.BEGIN_ARRAY) { // 正常解析数组 in.beginArray(); while (in.hasNext()) { Datum datum = new Gson().fromJson(in, Datum.class); list.add(datum); } in.endArray(); } return list; } }) .create();.addConverterFactory(GsonConverterFactory.create(gson))
内容的提问来源于stack exchange,提问作者Ankita
相关产品推荐
相关产品推荐

