能否使用JSONObject替代JsonObject实现Retrofit读取JSON数据?
能否用JSONObject替代JsonObject实现Retrofit的JSON数据读取?
你当前用的是Gson库的com.google.gson.JsonObject来接收Retrofit的响应,但如果想换成Android原生的org.json.JSONObject,直接替换返回类型是行不通的——因为你配置的GsonConverterFactory只能处理Gson库相关的类型,没法自动把响应转换成Android原生的JSONObject。不过有两种可行的方案可以实现需求:
方案一:通过ResponseBody手动解析成JSONObject
这是最直接的方式,不需要额外自定义转换器,步骤如下:
- 修改你的Retrofit接口定义,把返回类型改为
Call<ResponseBody>:
@POST("testservice") @FormUrlEncoded Call<ResponseBody> getRegisterUserData( @Header("x-dsn") String dsn, @Field("id") String id );
- 在Activity的回调中手动将响应体转换为JSONObject:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(API.BASE_URL) // 这里不需要移除GsonConverterFactory,只是暂时不用它处理这个接口的返回 .addConverterFactory(GsonConverterFactory.create()) .build(); YourApiService service = retrofit.create(YourApiService.class); Call<ResponseBody> call = service.getRegisterUserData(dsn, id); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful() && response.body() != null) { try { // 将响应体字符串转换为Android原生JSONObject String responseStr = response.body().string(); JSONObject jsonObject = new JSONObject(responseStr); // 在这里处理你的JSONObject数据 } catch (IOException | JSONException e) { e.printStackTrace(); // 处理解析异常 } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 处理请求失败逻辑 t.printStackTrace(); } });
方案二:自定义ConverterFactory支持JSONObject
如果你的项目中有多个接口都需要返回JSONObject,不想每次都手动解析,可以自定义一个转换器,让Retrofit能自动将响应转换为Android原生JSONObject:
- 先创建一个自定义的ResponseBodyConverter:
public class JSONObjectConverter implements Converter<ResponseBody, JSONObject> { @Override public JSONObject convert(ResponseBody value) throws IOException { try { return new JSONObject(value.string()); } catch (JSONException e) { throw new IOException("JSON parsing failed", e); } finally { value.close(); } } }
- 再创建对应的ConverterFactory:
public class JSONObjectConverterFactory extends Converter.Factory { public static JSONObjectConverterFactory create() { return new JSONObjectConverterFactory(); } @Nullable @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { // 当返回类型是JSONObject时,使用我们的自定义转换器 if (type == JSONObject.class) { return new JSONObjectConverter(); } return super.responseBodyConverter(type, annotations, retrofit); } }
- 最后在构建Retrofit时添加这个自定义ConverterFactory(注意要放在GsonConverterFactory之前,这样会优先处理JSONObject类型的返回):
Retrofit retrofit = new Retrofit.Builder() .baseUrl(API.BASE_URL) .addConverterFactory(JSONObjectConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();
- 现在你的接口就可以直接返回
Call<JSONObject>了:
@POST("testservice") @FormUrlEncoded Call<JSONObject> getRegisterUserData( @Header("x-dsn") String dsn, @Field("id") String id );
注意事项
- 方案一中,
response.body().string()只能调用一次,因为调用后响应体的流会被关闭,所以要先把字符串存起来再处理。 - 方案二中,自定义转换器要处理好异常,避免因为解析失败导致整个请求崩溃。
内容的提问来源于stack exchange,提问作者Taha Kirmani
相关产品推荐
相关产品推荐

