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

GSON处理JSON时遇空数组匹配对象问题求助

解决GSON解析空数组替代空对象的问题

这个坑我之前踩过!GSON默认的解析逻辑确实没法自动处理这种“用空数组[]代替空对象null”的奇葩JSON格式,不过咱们可以通过自定义TypeAdapter来完美适配,思路很简单:反序列化时判断当前字段如果是空数组,就返回null(或者你需要的空对象),否则正常解析成目标对象。

1. 写一个通用的自定义TypeAdapter

这个Adapter可以复用在所有需要处理的对象/集合类型上:

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 EmptyArrayAsNullAdapter<T> extends TypeAdapter<T> {
    private final TypeAdapter<T> delegate;

    public EmptyArrayAsNullAdapter(TypeAdapter<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public void write(JsonWriter out, T value) throws IOException {
        delegate.write(out, value);
    }

    @Override
    public T read(JsonReader in) throws IOException {
        // 检测到当前是数组类型
        if (in.peek() == JsonToken.BEGIN_ARRAY) {
            in.beginArray();
            // 判断数组是否为空
            if (!in.hasNext()) {
                in.endArray();
                return null; // 空数组直接返回null,也可以改成return new T()返回空对象(需确保T有无参构造)
            } else {
                // 非空数组但期望是对象的情况,根据业务需求处理,这里直接抛异常
                throw new IOException("Expected object but found non-empty array");
            }
        } else {
            // 正常解析对象
            return delegate.read(in);
        }
    }
}

2. 把Adapter注册到Gson实例

创建Gson的时候,将自定义Adapter绑定到目标类型上。比如假设你的实体类是Prize,业务模型类是AwardModel:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class GsonParser {
    public static void main(String[] args) {
        // 注册单个对象类型的Adapter
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Prize.class, new EmptyArrayAsNullAdapter<>(new Gson().getAdapter(Prize.class)))
                .create();

        // 测试空数组场景
        String emptyJson = "{\"prizes\":[]}";
        AwardModel emptyModel = gson.fromJson(emptyJson, AwardModel.class);
        // 此时emptyModel.getPrizes()会是null

        // 测试非空正常场景
        String nonEmptyJson = "{\"prizes\":[{\"year\":\"1902\",\"category\":\"physics\",\"share\":\"2\",\"motivation\":\"\\\"in recognition of the extraordinary service they rendered by their researches into the infl...\"}]}";
        AwardModel nonEmptyModel = gson.fromJson(nonEmptyJson, AwardModel.class);
        // 正常解析出Prize对象
    }
}

3. 针对List集合的特殊处理

如果你的prizes是List<Prize>类型,需要用TypeToken来指定泛型类型:

import com.google.gson.reflect.TypeToken;

// 注册List<Prize>类型的Adapter
Type prizeListType = new TypeToken<List<Prize>>() {}.getType();
Gson gson = new GsonBuilder()
        .registerTypeAdapter(prizeListType, new EmptyArrayAsNullAdapter<>(new Gson().getAdapter(prizeListType)))
        .create();

4. 仅针对特定字段处理(非全局)

如果只有个别字段有这个问题,不想全局生效,可以用@JsonAdapter注解直接标记在字段上:

public class AwardModel {
    // 单个对象字段
    @JsonAdapter(EmptyArrayAsNullAdapter.class)
    private Prize prizes;

    // 或者List集合字段
    // @JsonAdapter(EmptyArrayAsNullAdapter.class)
    // private List<Prize> prizes;
}

小提示

  • 如果业务需要空数组返回空对象而非null,可以把Adapter里的return null改成return new T(),但要确保目标类有无参构造函数。
  • 如果JSON里偶尔出现非空数组但期望是对象的异常场景,可以根据业务需求调整异常处理逻辑(比如跳过该字段、返回默认值等)。

内容的提问来源于stack exchange,提问作者Crushinz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:25:37