如何基于Cart的channel属性反序列化抽象Product子类型列表
方案1:修正注解配置(推荐,无需自定义反序列化器)
Jackson 2.9及以上版本本身支持EXTERNAL_PROPERTY类型的类型标识作用在集合字段上,你之前的写法不生效主要是两个配置问题:
@JsonSubTypes.Type的name属性需要和Channel枚举的实际序列化值完全匹配- 确保字段名和
@JsonTypeInfo指定的property属性值一致
正确配置示例:
public class Cart { private Channel channel; // 取值为Channel.ONLINE或Channel.PRINT @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "channel") @JsonSubTypes(value = { @JsonSubTypes.Type(value = OnlineProduct.class, name = "ONLINE"), // 与Channel枚举序列化值对应 @JsonSubTypes.Type(value = PrintProduct.class, name = "PRINT") }) private List<Product> products; // 其余属性、getter/setter省略,新增Cart属性时不需要修改此处配置 }
方案2:改进自定义反序列化器(适用于Jackson版本低、类型匹配逻辑复杂的场景)
你之前的自定义反序列化器不生效是因为第一次调用readValue时已经消费了全部JSON流,后续无法再读取products字段的内容。改进后的写法可以自动适配Cart的字段变更,不需要每次扩展Cart都修改反序列化器:
- 先将JSON解析为
JsonNode保留所有数据 - 复用Jackson默认的Cart反序列化器处理除
products外的所有字段 - 根据反序列化得到的
channel值单独解析products列表
实现代码:
public class CartDeserializer extends StdDeserializer<Cart> { private final JsonDeserializer<Object> defaultCartDeserializer; private final ObjectMapper objectMapper; public CartDeserializer(JsonDeserializer<?> defaultDeserializer, ObjectMapper objectMapper) { super(Cart.class); this.defaultCartDeserializer = (JsonDeserializer<Object>) defaultDeserializer; this.objectMapper = objectMapper; } @Override public Cart deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode root = p.readValueAsTree(); // 复用默认反序列化器处理所有普通字段,Cart新增属性时不需要修改这部分逻辑 Cart cart = (Cart) defaultCartDeserializer.deserialize(p.getCodec().treeAsTokens(root), ctxt); JsonNode productsNode = root.get("products"); if (productsNode != null && !productsNode.isNull()) { // 根据channel选择具体的Product实现类 Class<? extends Product> productClazz = Channel.ONLINE.equals(cart.getChannel()) ? OnlineProduct.class : PrintProduct.class; // 构造List的泛型类型进行反序列化 CollectionType productListType = objectMapper.getTypeFactory() .constructCollectionType(List.class, productClazz); List<Product> products = objectMapper.readValue( objectMapper.treeAsTokens(productsNode), productListType ); cart.setProducts(products); } return cart; } }
反序列化器注册方式:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { if (Cart.class.isAssignableFrom(beanDesc.getBeanClass())) { return new CartDeserializer(deserializer, mapper); } return deserializer; } }); mapper.registerModule(module);
内容的提问来源于stack exchange,提问作者Jazzschmidt
相关产品推荐
相关产品推荐

