You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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规则,且未明确指定字符串类型的处理方法。修改步骤如下:

  1. 修正Builder方法命名:由于@JsonPOJOBuilder(withPrefix = ""),Builder方法名需与字段名完全一致(无需with前缀)。
  2. 添加字符串类型处理方法并标记@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 22:25:30