Retrofit RxJava解析API响应异常:预期字符串却得到数组
解决Retrofit+RxJava解析时thumbnail字段类型不一致的问题
问题原因
服务器返回的thumbnail字段存在两种类型:有缩略图时是字符串,无缩略图时是空数组[],而你的POJO类中定义为String?,Gson无法自动适配这种类型不一致的情况,因此抛出java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY异常。
解决方案:自定义Gson TypeAdapter
编写自定义TypeAdapter,让Gson在解析时自动处理两种类型的情况:遇到数组时返回null,遇到字符串时直接返回该字符串。
步骤1:创建自定义TypeAdapter
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; public class ThumbnailTypeAdapter extends TypeAdapter<String> { @Override public void write(JsonWriter out, String value) throws IOException { if (value == null) { out.nullValue(); } else { out.value(value); } } @Override public String read(JsonReader in) throws IOException { // 遇到数组时跳过整个数组并返回null if (in.peek() == JsonToken.BEGIN_ARRAY) { in.beginArray(); while (in.hasNext()) { in.skipValue(); } in.endArray(); return null; } // 遇到字符串时直接读取返回 return in.nextString(); } }
步骤2:在POJO类中应用TypeAdapter
修改ResultPojo的thumbnail字段,添加@JsonAdapter注解指定适配器:
import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; class ResultPojo { @SerializedName("name") @Expose var name: String? = null @SerializedName("link") @Expose var link: String? = null @SerializedName("current_price") @Expose var currentPrice: Int? = null @SerializedName("original_price") @Expose var originalPrice: Int? = null @SerializedName("discounted") @Expose var discounted: Boolean? = null @SerializedName("thumbnail") @Expose @JsonAdapter(ThumbnailTypeAdapter.class) var thumbnail: String? = null @SerializedName("query_url") @Expose var queryUrl: String? = null }
步骤3:配置Retrofit(可选)
如果需要全局生效,可在构建Retrofit时注入自定义Gson实例:
Gson gson = new GsonBuilder() .registerTypeAdapter(String.class, new ThumbnailTypeAdapter()) .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build();
仅针对thumbnail字段处理的话,步骤2的注解已足够,无需全局注册。
其他可选方案
- 修改POJO字段类型:将
thumbnail改为Object?,在业务代码中手动判断类型转换,但会增加代码复杂度,不推荐。 - 协调服务器端修改:让服务器统一返回类型(比如无缩略图时返回空字符串
""),这是最彻底的方案,但需依赖服务器调整。
内容的提问来源于stack exchange,提问作者Emmi
相关产品推荐
相关产品推荐

