如何在GSON中仅对无效JSON用自定义反序列化,有效时忽略?
问题描述
调用某API时,它会返回两种格式的响应(类名为示例):
错误响应
{ "CustomObject_1" : { "CustomObject_1.1" : { ... }, "CustomObject_1.2" : [ [ ] ] }, "CustomObject_2" : { ... } }
正确响应
{ "CustomObject_1" : { "CustomObject_1.1" : { ... }, "CustomObject_1.2" : [ { "CustomObject_1.2.1" : { ... } } ] }, "CustomObject_2" : { ... } }
两者核心区别是CustomObject_1.2:它既可能是包含多层自定义对象的结构,也可能是空数组。
编写的自定义反序列化器CustomObject_1.2Deserializer能处理错误响应,但会导致正确响应的CustomObject_1.2变为null,无法使用默认序列化逻辑。
当前反序列化器代码
class CustomObject_1.2Deserializer { public CustomObject_1.2 deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonArray()) { JsonArray jsonArray = json.getAsJsonArray(); if (jsonArray.size() == 0) { System.out.println(jsonArray); // 返回空的Totals对象 return new CustomObject_1.2(); } } else if (json.isJsonObject()) { JsonObject jsonObject = json.getAsJsonObject(); if (jsonObject.has("CustomObject_1.2.1") && jsonObject.get("CustomObject_1.2.1").isJsonArray()) { JsonArray competitorsArray = jsonObject.getAsJsonArray("competitors"); System.out.println(competitorsArray); // 有效对象,期望使用默认序列化 } } return null; } }
处理GSON序列化的函数
private MyDtoInterface processResponse(String message) { MyDtoInterface mDto = null; try { Gson gson = new GsonBuilder() .registerTypeAdapter(CustomObject_1.2.class, new CustomObject_1.2Deserializer()) .create(); mDto = gson.fromJson(message, CustomparentDTO.class); } catch (Exception e) { System.out.println("Json format not compatible with ParentDTO"); } return mDto; }
当前现象
- 错误响应能生成正常DTO:
CustomObject_1.2会被初始化为空对象 - 正确响应的
CustomObject_1.2所有元素变为null,无法正确反序列化
需求:仅对无效JSON(空数组的情况)进行自定义处理,有效JSON时自动使用GSON的默认序列化逻辑,避免手动构建嵌套复杂的CustomObject_1.2对象。
解决方案
问题出在当前反序列化器遇到有效JSON时,没有触发GSON的默认反序列化逻辑,直接返回了null。要实现“仅处理无效情况,有效时用默认逻辑”,可以通过JsonDeserializationContext.deserialize()方法调用GSON的默认序列化器。
修改后的反序列化器代码
class CustomObject_1_2Deserializer implements JsonDeserializer<CustomObject_1.2> { @Override public CustomObject_1.2 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { // 处理错误情况:空数组(含嵌套空数组的场景) if (json.isJsonArray()) { JsonArray outerArray = json.getAsJsonArray(); // 适配外层数组直接为空,或外层数组仅包含内层空数组的情况 if (outerArray.isEmpty() || (outerArray.size() == 1 && outerArray.get(0).isJsonArray() && outerArray.get(0).getAsJsonArray().isEmpty())) { return new CustomObject_1.2(); } } // 有效情况:交给GSON默认反序列化处理 return context.deserialize(json, typeOfT); } }
关键修改说明
- 移除多余的有效对象判断逻辑,只要不是需要特殊处理的空数组场景,直接交给默认序列化器处理
- 用
context.deserialize(json, typeOfT)替代返回null,让GSON按照正常DTO映射规则反序列化有效JSON - 修正了Java类名的语法问题(原类名不符合Java命名规范,改为
CustomObject_1_2Deserializer并实现JsonDeserializer接口) - 增加了对嵌套空数组场景的适配,覆盖API返回的错误响应格式
调整后的序列化处理函数
private MyDtoInterface processResponse(String message) { MyDtoInterface mDto = null; try { Gson gson = new GsonBuilder() .registerTypeAdapter(CustomObject_1.2.class, new CustomObject_1_2Deserializer()) .create(); mDto = gson.fromJson(message, CustomparentDTO.class); } catch (Exception e) { System.out.println("Json format not compatible with ParentDTO"); e.printStackTrace(); // 建议添加异常打印,方便排查问题 } return mDto; }
内容的提问来源于stack exchange,提问作者Atram
相关产品推荐
相关产品推荐

