Jackson如何反序列化Map或单个值?实现通配符映射转换
解决Jackson反序列化Map字段支持通配符字符串的问题
问题背景
我们需要将包含通配符字符串的JSON输入反序列化为FooBar类,其中mapField字段在输入为"*"时,要转换为{"*": ["*"]}的Map结构。原代码添加Builder方法后出现反序列化错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of "java.util.LinkedHashMap" (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('*')
解决方案
核心问题在于原Builder方法命名不符合Jackson的Builder规则,且未明确指定字符串类型的处理方法。修改步骤如下:
- 修正Builder方法命名:由于
@JsonPOJOBuilder(withPrefix = ""),Builder方法名需与字段名完全一致(无需with前缀)。 - 添加字符串类型处理方法并标记@JsonSetter:让Jackson识别该方法可处理字符串类型的
mapField输入,同时保留常规Map类型的处理方法。
修改后的完整代码:
@Value @Builder @JsonDeserialize(builder = FooBar.FooBarBuilder.class) public class FooBar { private final String id; private final String thing; private final Map<String, List<String>> mapField; @JsonPOJOBuilder(withPrefix = "") @JsonIgnoreProperties(ignoreUnknown = true) public static final class FooBarBuilder { // 处理通配符字符串输入 @JsonSetter public FooBarBuilder mapField(String value) { if ("*".equals(value)) { this.mapField = new HashMap<>(); this.mapField.put("*", List.of("*")); } return this; } // 处理常规Map格式输入 public FooBarBuilder mapField(Map<String, List<String>> mapField) { this.mapField = mapField; return this; } } }
原理说明
@JsonSetter注解告诉Jackson,当mapField字段为字符串类型时,优先调用该方法处理。- 两个同名方法(参数类型不同)实现了重载,Jackson会根据输入的实际类型自动匹配对应的方法:
- 输入为
"*"时,调用字符串参数的方法,转换为目标Map结构。 - 输入为常规Map格式时,调用Map参数的方法直接赋值。
- 输入为
内容的提问来源于stack exchange,提问作者ntacp
相关产品推荐
相关产品推荐

