Jackson反序列化多态类型:处理值为原始类型或数组的场景
解决Jackson反序列化动态Wrapper对象(支持单值/数组)的问题
问题根源
你当前的报错是因为使用@JsonTypeInfo(As.WRAPPER_OBJECT)时,Jackson会将"value"键对应的整个内容(单值或数组)直接当作MyValue的实例来反序列化。而你的原始MyValue只有接受基本类型的构造函数,没有处理数组的逻辑,因此遇到数组时无法匹配,抛出类型不匹配异常。
解决方案
方案1:统一用Object字段兼容单值/数组
修改MyValue类,使用一个带@JsonCreator的构造函数接受任意类型的输入,直接赋值给Object字段:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes({ @JsonSubTypes.Type(value = MyValue.class, name = "value"), @JsonSubTypes.Type(value = MyVariable.class, name = "variable") }) public interface MyOperand {} public class MyValue implements MyOperand { private Object value; // 用@JsonCreator指定构造逻辑,兼容单值、数组等任意类型 @JsonCreator public MyValue(@JsonProperty("value") Object value) { this.value = value; } public Object getValue() { return value; } } // MyVariable类示例(补充完整) public class MyVariable implements MyOperand { private String variable; @JsonCreator public MyVariable(@JsonProperty("variable") String variable) { this.variable = variable; } public String getVariable() { return variable; } }
方案2:统一转成List<Object>兼容单值/数组
如果希望无论输入是单值还是数组,都统一存储为List,可以在构造函数中手动处理转换逻辑,无需额外启用ACCEPT_SINGLE_VALUE_AS_ARRAY:
public class MyValue implements MyOperand { private List<Object> value; @JsonCreator public MyValue(@JsonProperty("value") Object input) { if (input instanceof List) { this.value = new ArrayList<>((List<Object>) input); } else { // 单值转成单元素列表 this.value = Collections.singletonList(input); } } public List<Object> getValue() { return value; } }
关键说明
- 移除原来按基本类型拆分的多个构造函数,改用单一的
@JsonCreator构造函数,让Jackson明确知道如何从任意类型的输入创建MyValue实例。 @JsonProperty("value")注解必须添加,否则Jackson无法将Wrapper对象中的值绑定到构造函数参数。- 方案2的好处是后续业务逻辑无需判断值是单值还是数组,统一按列表处理即可。
内容的提问来源于stack exchange,提问作者nogridbag
相关产品推荐
相关产品推荐

