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

如何通过Jackson实现TS动态类型到Java多类型对象的无标识反序列化

解决方案:自定义Jackson反序列化器处理多类型字段

因为无法修改前端模型且不能添加类型标识,直接用@JsonTypeInfo(Id.DEDUCTION)会因String与Object的JSON结构冲突失败,同时数组会被默认转成LinkedHashMap数组,所以需要自定义反序列化器手动判断JSON节点类型并完成对应转换。

实现步骤

1. 编写自定义反序列化器OptionDeserializer

继承JsonDeserializer<Object>,通过JsonParser获取JSON节点类型,分别处理三种情况:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class OptionDeserializer extends JsonDeserializer<Object> {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Override
    public Object deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        JsonToken token = parser.getCurrentToken();
        JsonNode node = parser.readValueAsTree();

        // 处理字符串类型
        if (token == JsonToken.VALUE_STRING) {
            return node.asText();
        }
        // 处理数组类型(DetFieldOption集合)
        else if (token == JsonToken.START_ARRAY) {
            return OBJECT_MAPPER.convertValue(node, Collection.class);
        }
        // 处理Map类型(Integer为键,String为值)
        else if (token == JsonToken.START_OBJECT) {
            Map<Integer, String> map = new HashMap<>();
            node.fields().forEachRemaining(entry -> {
                try {
                    Integer key = Integer.parseInt(entry.getKey());
                    String value = entry.getValue().asText();
                    map.put(key, value);
                } catch (NumberFormatException e) {
                    // 若键不是合法Integer,可根据业务需求抛出异常或忽略
                    throw new IllegalArgumentException("Map key must be Integer type", e);
                }
            });
            return map;
        }
        // 其他类型根据业务处理,比如返回null或抛出异常
        throw new IllegalArgumentException("Unsupported option type: " + token);
    }
}

2. 在Java模型的option字段上绑定反序列化器

修改你的Field模型类,给option字段添加@JsonDeserialize注解指定自定义反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class Field {
    // 其他字段...

    @JsonDeserialize(using = OptionDeserializer.class)
    private Object option;

    // getter、setter...
}

3. 验证反序列化结果

反序列化后可通过instanceof判断类型并处理:

Field field = objectMapper.readValue(jsonString, Field.class);
Object option = field.getOption();

if (option instanceof String) {
    // 处理字符串类型逻辑
    String pluginStr = (String) option;
} else if (option instanceof Collection) {
    // 处理DetFieldOption集合逻辑
    Collection<DetFieldOption> options = (Collection<DetFieldOption>) option;
} else if (option instanceof Map) {
    // 处理Integer-String Map逻辑
    Map<Integer, String> optionMap = (Map<Integer, String>) option;
}

关键说明

  • 字符串判断:直接通过JsonToken.VALUE_STRING识别,避免与Object类型冲突
  • 数组转集合:利用ObjectMapper.convertValue直接将JSON数组转换为Collection<DetFieldOption>,无需手动遍历
  • Map键处理:手动将JSON对象的字符串键转为Integer,确保符合业务要求
  • 异常处理:可根据实际业务调整非法类型或非法键的处理逻辑(比如忽略错误键、返回默认值等)

内容的提问来源于stack exchange,提问作者usr-local-ΕΨΗΕΛΩΝ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:00:42