如何准确在Retrofit GET请求中嵌入查询参数?
- 内容介绍
- 相关推荐
本文共计955个文字,预计阅读时间需要4分钟。
原文详解 Retrofit 在 Android 中开发 HTTP GET 请求时,如何正确通过 URL 查询参数(Query Parameters)传递数据,避免因类型不匹配、参数名错误或空值导致的 Null 响应问题。
在使用 Retrofit 发起 GET 请求时,必须严格区分请求方式与参数承载位置:GET 请求的参数只能通过 URL 查询字符串(query string)传递,不能放在请求体(body)中——这与 POST/PUT 请求有本质区别。你提供的 Postman 截图显示参数以 JSON 形式置于 Body,但这实际是 Postman 的误用行为:标准 HTTP GET 不支持 body,Postman 此时可能隐式转为 POST,或服务端做了非标准兼容。而 Retrofit 严格遵循 HTTP 规范,@GET 注解下所有参数必须通过 @Query 显式声明并拼接到 URL 末尾。
首先,修正接口定义中的关键错误:
✅ 正确写法(参数名需与 API 文档完全一致):
public interface ShipRocketServiceAbilityInterface { @GET("courier/serviceability/") Call<ShipRocketServiceabilityResponse> getService( @Query("pickup_postcode") String pickupPostcode, // 注意:原问题中 Postman 用的是 "pickup_postcode",但代码写成 "pickup_postcode" → 拼写必须一致! @Query("delivery_postcode") String deliveryPostcode, @Query("cod") String cod, @Query("weight") String weight ); }
⚠️ 原代码存在多个编译期/运行期隐患:
- 类型不匹配:boolean cod = "1" 和 float weight = "1" 是非法赋值(字符串不能直接赋给基本类型),会导致编译失败;
- 参数名不一致:Postman 中字段为 "pickup_postcode"(下划线),但接口中误写为 "pickup_postcode"(少一个 'o'?需核对文档);
- 空值风险:若 response.body() 为 null,说明解析失败,常见于 JSON 结构与 ShipRocketServiceabilityResponse 模型类字段名/类型不匹配(如 currency 字段不存在或命名不一致)。
✅ 正确调用示例:
// 确保参数类型为 String(@Query 要求) String pickupPostcode = "600114"; String deliveryPostcode = "600125"; String cod = "1"; // 不是 boolean,也不是 int String weight = "1"; // 不是 float Call<ShipRocketServiceabilityResponse> call = shipRocket.getService( pickupPostcode, deliveryPostcode, cod, weight ); call.enqueue(new Callback<ShipRocketServiceabilityResponse>() { @Override public void onResponse(Call<ShipRocketServiceabilityResponse> call, Response<ShipRocketServiceabilityResponse> response) { if (response.isSuccessful() && response.body() != null) { // ✅ 安全访问 String currency = response.body().getCurrency(); Log.d("API", "Currency: " + currency); } else { Log.e("API", "Response error: " + response.code() + " " + response.message()); } } @Override public void onFailure(Call<ShipRocketServiceabilityResponse> call, Throwable t) { Log.e("API", "Network or parsing error", t); } });
? 关键注意事项:
- 始终校验 response.isSuccessful() 和 response.body() != null —— 网络错误、4xx/5xx 响应、JSON 解析失败均可能导致 body 为 null;
- 模型类必须精确映射响应 JSON:例如若返回 JSON 含 "currency": "INR",则 ShipRocketServiceabilityResponse 中需有 private String currency; 及对应 getter;
- 调试技巧:启用 OkHttp 日志拦截器,查看实际发出的 URL(如 .../serviceability/?pickup_postcode=600114&delivery_postcode=600125...),确认参数是否拼接正确;
-
进阶建议:对多参数 GET 请求,可封装为 @QueryMap Map<String, String> 提升可维护性:
@GET("courier/serviceability/") Call<ShipRocketServiceabilityResponse> getService(@QueryMap Map<String, String> options); // 调用: Map<String, String> params = new HashMap<>(); params.put("pickup_postcode", "600114"); params.put("delivery_postcode", "600125"); params.put("cod", "1"); params.put("weight", "1");
遵循以上规范,即可彻底解决 Retrofit GET 请求返回 null 的问题,确保参数准确送达服务端并正确解析响应。
本文共计955个文字,预计阅读时间需要4分钟。
原文详解 Retrofit 在 Android 中开发 HTTP GET 请求时,如何正确通过 URL 查询参数(Query Parameters)传递数据,避免因类型不匹配、参数名错误或空值导致的 Null 响应问题。
在使用 Retrofit 发起 GET 请求时,必须严格区分请求方式与参数承载位置:GET 请求的参数只能通过 URL 查询字符串(query string)传递,不能放在请求体(body)中——这与 POST/PUT 请求有本质区别。你提供的 Postman 截图显示参数以 JSON 形式置于 Body,但这实际是 Postman 的误用行为:标准 HTTP GET 不支持 body,Postman 此时可能隐式转为 POST,或服务端做了非标准兼容。而 Retrofit 严格遵循 HTTP 规范,@GET 注解下所有参数必须通过 @Query 显式声明并拼接到 URL 末尾。
首先,修正接口定义中的关键错误:
✅ 正确写法(参数名需与 API 文档完全一致):
public interface ShipRocketServiceAbilityInterface { @GET("courier/serviceability/") Call<ShipRocketServiceabilityResponse> getService( @Query("pickup_postcode") String pickupPostcode, // 注意:原问题中 Postman 用的是 "pickup_postcode",但代码写成 "pickup_postcode" → 拼写必须一致! @Query("delivery_postcode") String deliveryPostcode, @Query("cod") String cod, @Query("weight") String weight ); }
⚠️ 原代码存在多个编译期/运行期隐患:
- 类型不匹配:boolean cod = "1" 和 float weight = "1" 是非法赋值(字符串不能直接赋给基本类型),会导致编译失败;
- 参数名不一致:Postman 中字段为 "pickup_postcode"(下划线),但接口中误写为 "pickup_postcode"(少一个 'o'?需核对文档);
- 空值风险:若 response.body() 为 null,说明解析失败,常见于 JSON 结构与 ShipRocketServiceabilityResponse 模型类字段名/类型不匹配(如 currency 字段不存在或命名不一致)。
✅ 正确调用示例:
// 确保参数类型为 String(@Query 要求) String pickupPostcode = "600114"; String deliveryPostcode = "600125"; String cod = "1"; // 不是 boolean,也不是 int String weight = "1"; // 不是 float Call<ShipRocketServiceabilityResponse> call = shipRocket.getService( pickupPostcode, deliveryPostcode, cod, weight ); call.enqueue(new Callback<ShipRocketServiceabilityResponse>() { @Override public void onResponse(Call<ShipRocketServiceabilityResponse> call, Response<ShipRocketServiceabilityResponse> response) { if (response.isSuccessful() && response.body() != null) { // ✅ 安全访问 String currency = response.body().getCurrency(); Log.d("API", "Currency: " + currency); } else { Log.e("API", "Response error: " + response.code() + " " + response.message()); } } @Override public void onFailure(Call<ShipRocketServiceabilityResponse> call, Throwable t) { Log.e("API", "Network or parsing error", t); } });
? 关键注意事项:
- 始终校验 response.isSuccessful() 和 response.body() != null —— 网络错误、4xx/5xx 响应、JSON 解析失败均可能导致 body 为 null;
- 模型类必须精确映射响应 JSON:例如若返回 JSON 含 "currency": "INR",则 ShipRocketServiceabilityResponse 中需有 private String currency; 及对应 getter;
- 调试技巧:启用 OkHttp 日志拦截器,查看实际发出的 URL(如 .../serviceability/?pickup_postcode=600114&delivery_postcode=600125...),确认参数是否拼接正确;
-
进阶建议:对多参数 GET 请求,可封装为 @QueryMap Map<String, String> 提升可维护性:
@GET("courier/serviceability/") Call<ShipRocketServiceabilityResponse> getService(@QueryMap Map<String, String> options); // 调用: Map<String, String> params = new HashMap<>(); params.put("pickup_postcode", "600114"); params.put("delivery_postcode", "600125"); params.put("cod", "1"); params.put("weight", "1");
遵循以上规范,即可彻底解决 Retrofit GET 请求返回 null 的问题,确保参数准确送达服务端并正确解析响应。

