使用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
相关产品推荐
相关产品推荐

