You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:35:21