Jackson反序列化时如何映射org.apache.commons.lang3.tuple.Pair至具体类型?
org.apache.commons.lang3.tuple.Pair失败的解决方法 问题场景
待反序列化的JSON
{ "page" : 0, "size" : 4, "leafDistribution" : { "D_a" : { "1" : 4 }, "D_b" : { "3" : 4 } } }
Npd类定义
@Getter public class Npd { private Integer page; private Integer size; protected Map<String, Pair<Integer, Integer>> leafDistribution; }
报错信息
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of
org.apache.commons.lang3.tuple.Pair(no Creators, like default constructor, exist): abstract
types either need to be mapped to concrete types, have custom deserializer, or contain additional
type information
at [Source: (String)"{
"page" : 0,
"size" : 4,
"leafDistribution" : {
"D_a" : {
"1" : 4
},
"D_b" : {
"3" : 4
}
}
}"; line: 5, column: 15] (through reference chain:
prac.filter.dto.NestedFilterRequestDto["leafDistribution"]->java.util.LinkedHashMap["D_a"])
无效的Mixin尝试代码
public abstract class NpdMixin { @JsonDeserialize(as= org.apache.commons.lang3.tuple.MutablePair.class) public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<org.apache.commons.lang3.tuple.Pair<L, R>>, Serializable { } }
有效解决方法
方法一:直接在字段上指定反序列化实现类
无需编写Mixin,直接在leafDistribution字段上添加@JsonDeserialize注解,用contentAs指定Map值的具体Pair实现类(如MutablePair或ImmutablePair):
@Getter public class Npd { private Integer page; private Integer size; @JsonDeserialize(contentAs = org.apache.commons.lang3.tuple.MutablePair.class) protected Map<String, Pair<Integer, Integer>> leafDistribution; }
方法二:正确使用Mixin注解
之前的Mixin写法错误,需直接为原Pair类定义Mixin,而非在NpdMixin内部嵌套新类:
- 定义Pair的Mixin类:
@JsonDeserialize(as = org.apache.commons.lang3.tuple.MutablePair.class) public abstract class PairMixin {}
- 在
ObjectMapper中注册该Mixin:
ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(org.apache.commons.lang3.tuple.Pair.class, PairMixin.class);
方法三:自定义反序列化器(灵活适配场景)
如果JSON结构与Pair的映射需要特殊处理,可自定义反序列化器:
- 编写反序列化器类:
public class PairDeserializer extends StdDeserializer<Pair<Integer, Integer>> { protected PairDeserializer() { super(Pair.class); } @Override public Pair<Integer, Integer> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); // 提取JSON单键值对转为Pair Map.Entry<String, JsonNode> entry = node.fields().next(); Integer key = Integer.parseInt(entry.getKey()); Integer value = entry.getValue().asInt(); return MutablePair.of(key, value); } }
- 在Npd类字段上注册该反序列化器:
@Getter public class Npd { private Integer page; private Integer size; @JsonDeserialize(contentUsing = PairDeserializer.class) protected Map<String, Pair<Integer, Integer>> leafDistribution; }
内容的提问来源于stack exchange,提问作者Saptarshi

