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

使用GSON解析时而为对象时而为数组的JSON字段问题求助

解决GSON解析时字段时而为对象时而为数组的问题

嘿,我太懂你遇到的这个糟心问题了!GSON默认对类型匹配要求很严格,同一个字段一会儿是数组、一会儿是单个对象,直接用ArrayList<ValueModel>肯定会炸锅。不过咱们用自定义反序列化器就能轻松搞定,我给你一步步捋清楚:

第一步:先修复内部类的小隐患

你的ValueModel是MyModel的非静态内部类,GSON解析时可能会因为需要外部类实例而出问题,先把它改成静态内部类:

public class MyModel implements Serializable {
    @SerializedName("key")
    @Expose
    public String key;
    
    @SerializedName("value")
    @Expose
    public ArrayList<ValueModel> value;
    
    // 改成静态内部类,避免解析时的实例依赖问题
    public static class ValueModel implements Serializable {
        @SerializedName("id")
        @Expose
        public String id;
        @SerializedName("name")
        @Expose
        public String name;
    }
}

第二步:编写自定义反序列化器

咱们写一个JsonDeserializer,专门处理value字段的两种情况,把它统一转成ArrayList<ValueModel>:

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type;
import java.util.ArrayList;

public class ValueListDeserializer implements JsonDeserializer<ArrayList<MyModel.ValueModel>> {
    @Override
    public ArrayList<MyModel.ValueModel> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        ArrayList<MyModel.ValueModel> valueList = new ArrayList<>();
        
        if (json.isJsonArray()) {
            // 如果是数组,逐个解析元素加入列表
            JsonArray jsonArray = json.getAsJsonArray();
            for (JsonElement element : jsonArray) {
                MyModel.ValueModel model = context.deserialize(element, MyModel.ValueModel.class);
                valueList.add(model);
            }
        } else if (json.isJsonObject()) {
            // 如果是单个对象,解析后直接加入列表
            MyModel.ValueModel model = context.deserialize(json, MyModel.ValueModel.class);
            valueList.add(model);
        }
        
        return valueList;
    }
}

第三步:注册反序列化器(两种方式选一种)

方式一:创建Gson实例时全局注册

在构建Gson对象的时候,把咱们的反序列化器注册进去,这样所有解析都会生效:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(
                new TypeToken<ArrayList<MyModel.ValueModel>>(){}.getType(),
                new ValueListDeserializer()
        )
        .create();

// 现在两种JSON格式都能正常解析了
MyModel arrayModel = gson.fromJson(arrayJsonString, MyModel.class);
MyModel objectModel = gson.fromJson(objectJsonString, MyModel.class);

方式二:直接在字段上用注解指定

不想每次创建Gson都注册的话,直接在value字段上加上@JsonAdapter注解,精准指定该字段的反序列化器:

public class MyModel implements Serializable {
    @SerializedName("key")
    @Expose
    public String key;
    
    @SerializedName("value")
    @Expose
    @JsonAdapter(ValueListDeserializer.class) // 给这个字段绑定自定义解析器
    public ArrayList<ValueModel> value;
    
    public static class ValueModel implements Serializable {
        @SerializedName("id")
        @Expose
        public String id;
        @SerializedName("name")
        @Expose
        public String name;
    }
}

这样用普通的new Gson()就能正常解析两种格式的JSON了。

现在不管是数组形式还是对象形式的响应,解析后value字段都会是一个ArrayList,里面包含对应的ValueModel实例,再也不会抛出解析异常啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:24:07