@Override
public List
JsonDeserializationContext context) throws JsonParseException {
在移动开发和后端服务交互中,我们常遇到JSON结构动态变化的场景。有时接口返回单个对象,有时返回对象数组,这种不确定性给反序列化带来挑战。本文将深入探讨如何通过Gson实现优雅的统一解析方案。
假设我们有个内容API接口,当查询单个文章时返回:
json
{
"title": "Android性能优化",
"keywords": ["移动端","性能"],
"content": "正文内容..."
}
而批量查询时返回:
json
[
{
"title": "Kotlin协程指南",
"keywords": ["异步","JVM"],
"content": "正文内容..."
},
//...更多文章
]
传统解析方式需要预先知道数据结构形态,这种不确定性会导致:
- 需要编写重复的解析逻辑
- 类型判断代码污染业务逻辑
- 出现意外结构时崩溃风险高
通过实现JsonDeserializer
接口,我们可以接管反序列化过程:
java
public class DynamicAdapter implements JsonDeserializer<List
@Override
public List
JsonDeserializationContext context) throws JsonParseException {
List<Article> articles = new ArrayList<>();
if (json.isJsonArray()) {
for (JsonElement element : json.getAsJsonArray()) {
articles.add(context.deserialize(element, Article.class));
}
} else if (json.isJsonObject()) {
articles.add(context.deserialize(json, Article.class));
}
return articles;
}
}
注册适配器:
java
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<List<Article>>(){}.getType(),
new DynamicAdapter())
.create();
对于更复杂的场景,可以采用类型推导策略:
java
public
try {
JsonElement element = JsonParser.parseString(jsonStr);
if (element.isJsonArray()) {
Type listType = TypeToken.getParameterized(List.class, itemClass).getType();
return gson.fromJson(element, listType);
} else {
return gson.fromJson(element, itemClass);
}
} catch (JsonSyntaxException e) {
// 异常处理逻辑
}
}
isJsonNull()
避免NPE当处理泛型集合时,Gson的TypeToken
可以保留类型信息:
java
// 获取带泛型的Type
Type articleListType = new TypeToken<List
// 安全转换
List
对于多层嵌套结构(如Map<String, List<Article>>
),这种方法尤其有效。
某电商App的商品接口可能出现:
- 单品详情(单个JSON对象)
- 搜索结果(对象数组)
- 猜你喜欢(带分页信息的包装对象)
通过统一解析策略,客户端的处理代码量减少40%,且再未出现解析相关的崩溃。
Gson的动态解析能力如同瑞士军刀,关键在于:
1. 理解JsonElement
的层次结构
2. 合理利用运行时类型信息
3. 建立健壮的异常处理机制
当面对不确定的JSON结构时,这种方案既保持了类型安全,又兼顾了灵活性,是处理动态接口响应的优选方案。