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

如何在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);
    }
}

关键修改说明

  1. 移除多余的有效对象判断逻辑,只要不是需要特殊处理的空数组场景,直接交给默认序列化器处理
  2. 用context.deserialize(json, typeOfT)替代返回null,让GSON按照正常DTO映射规则反序列化有效JSON
  3. 修正了Java类名的语法问题(原类名不符合Java命名规范,改为CustomObject_1_2Deserializer并实现JsonDeserializer接口)
  4. 增加了对嵌套空数组场景的适配,覆盖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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:59:59