如何通过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-ΕΨΗΕΛΩΝ
相关产品推荐
相关产品推荐

