如何用GSON适配同时为数组和对象的meta_data字段转Java对象?
解决GSON解析同时支持数组和对象的
meta_data字段问题 这个问题是GSON处理多类型JSON字段的典型场景——你的meta_data字段在不同type下分别是对象数组和键值对对象,但当前Java类只定义了单个MetaData对象,导致解析数组时类型不匹配抛出异常。下面给出两种实用的解决方案,无需修改JSON结构:
方案1:统一解析为List<MetaData>
如果不需要保留assinatura类型里的键(比如示例中的4、5),可以把meta_data统一转成列表:
步骤1:调整LineItem类的字段类型
把原来的单个MetaData字段改成List<MetaData>:
public class LineItem { @SerializedName("meta_data") @Expose private List<MetaData> metaData; // 生成对应的getter和setter方法 }
步骤2:自定义JSON反序列化器
创建一个JsonDeserializer实现类,判断JSON的类型并分别处理:
import com.google.gson.*; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; public class MetaDataListDeserializer implements JsonDeserializer<List<MetaData>> { @Override public List<MetaData> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { List<MetaData> metaDataList = new ArrayList<>(); if (json.isJsonArray()) { // 处理数组类型的meta_data JsonArray jsonArray = json.getAsJsonArray(); for (JsonElement element : jsonArray) { MetaData metaData = context.deserialize(element, MetaData.class); metaDataList.add(metaData); } } else if (json.isJsonObject()) { // 处理键值对对象类型的meta_data,忽略原键直接转成列表元素 JsonObject jsonObject = json.getAsJsonObject(); for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { MetaData metaData = context.deserialize(entry.getValue(), MetaData.class); metaDataList.add(metaData); } } return metaDataList; } }
步骤3:注册反序列化器并解析
创建Gson实例时注册自定义的反序列化器,再进行JSON解析:
Gson gson = new GsonBuilder() .registerTypeAdapter(new TypeToken<List<MetaData>>(){}.getType(), new MetaDataListDeserializer()) .create(); // 替换成你的根类类型 YourRootClass[] result = gson.fromJson(yourJsonString, YourRootClass[].class);
方案2:统一解析为Map<String, MetaData>
如果需要保留assinatura类型里的键(比如示例中的4、5),可以把meta_data转成键值对映射:
步骤1:调整LineItem类的字段类型
改成Map<String, MetaData>:
public class LineItem { @SerializedName("meta_data") @Expose private Map<String, MetaData> metaData; // 生成对应的getter和setter方法 }
步骤2:自定义JSON反序列化器
创建适配Map的反序列化器,数组类型可以用id或索引作为键:
import com.google.gson.*; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; public class MetaDataMapDeserializer implements JsonDeserializer<Map<String, MetaData>> { @Override public Map<String, MetaData> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { Map<String, MetaData> metaDataMap = new HashMap<>(); if (json.isJsonArray()) { // 处理数组类型,这里用MetaData的id作为key,也可以用索引 JsonArray jsonArray = json.getAsJsonArray(); for (JsonElement element : jsonArray) { MetaData metaData = context.deserialize(element, MetaData.class); metaDataMap.put(metaData.getId(), metaData); } } else if (json.isJsonObject()) { // 处理键值对对象类型,直接使用原键 JsonObject jsonObject = json.getAsJsonObject(); for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { MetaData metaData = context.deserialize(entry.getValue(), MetaData.class); metaDataMap.put(entry.getKey(), metaData); } } return metaDataMap; } }
步骤3:注册反序列化器并解析
Gson gson = new GsonBuilder() .registerTypeAdapter(new TypeToken<Map<String, MetaData>>(){}.getType(), new MetaDataMapDeserializer()) .create(); // 替换成你的根类类型 YourRootClass[] result = gson.fromJson(yourJsonString, YourRootClass[].class);
为什么原来的代码会报错?
你定义的private MetaData metaData;告诉GSON期望解析一个单个对象(BEGIN_OBJECT),但当遇到type:"unico"时,meta_data是数组(BEGIN_ARRAY),类型不匹配,所以抛出IllegalStateException异常。自定义反序列化器的核心就是在解析时动态判断JSON结构,做适配转换。
内容的提问来源于stack exchange,提问作者Pedro Samú
相关产品推荐
相关产品推荐

