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

如何借助Jackson将JSON数组部分反序列化为HashMap<String,Integer>

问题描述

我有如下JSON数组:

[
  {
    "a": 1,         
    "b": 2,                  
    "c": "one",
    "d": 3                     
  },
  {
    "a": 4,         
    "b": 5,                  
    "c": "two",
    "d": 6                     
  },
  {
    "a": 7,         
    "b": 8,                  
    "c": "three",
    "d": 9                     
  }
]

我需要借助Jackson将其转换为HashMap<String,Integer>类型,最终结构如下,其中键为每个元素的"c"字段值,值为对应元素的"b"字段值:

{
  "one": 2,
  "two": 5,
  "three": 8
}

我尝试过使用自定义反序列化器实现该需求,但无法正确注册,也不确定该实现方式是否正确。另外我拿到的JSON是直接的字符串格式,没有外层嵌套包装对象,因此无法使用@JsonDeserialize(using = CustomDeserializer.class)这类注解指定反序列化器。
因此我尝试直接在ObjectMapper中注册自定义反序列化器,使用了如下配置,但配置没有生效:

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(new TypeReference<HashMap<String,Integer>>(){}, new CustomDeserializer());

请问我哪里配置有误?希望能得到解决方案。


解决方案

配置错误原因

你调用SimpleModule#addDeserializer时入参不符合要求,该方法第一个参数需要传入反序列化目标的Class对象,你传入的TypeReference不会被识别,因此注册的自定义反序列化器无法匹配到对应反序列化场景,自然不生效。

可选实现方案

方案1:无需自定义反序列化器(更简单,推荐)

先将JSON数组反序列化为中间结构,再手动提取字段生成目标Map,代码逻辑清晰且不会影响全局ObjectMapper的行为:

ObjectMapper objectMapper = new ObjectMapper();
// 先解析为JsonNode数组
JsonNode arrayNode = objectMapper.readTree(jsonStr);
HashMap<String, Integer> result = new HashMap<>();
for (JsonNode item : arrayNode) {
    result.put(item.get("c").asText(), item.get("b").asInt());
}

你也可以定义简单实体类承接数组元素,通过流处理转换:

// 定义数组元素对应的实体类
@Data
public class Element {
    private String c;
    private Integer b;
    // 未声明的a、d字段Jackson会自动忽略
}

// 转换逻辑
List<Element> elementList = objectMapper.readValue(jsonStr, new TypeReference<List<Element>>() {});
HashMap<String, Integer> result = elementList.stream()
        .collect(Collectors.toMap(Element::getC, Element::getB, (oldVal, newVal) -> oldVal, HashMap::new));

方案2:正确注册自定义反序列化器

如果需要直接通过反序列化得到目标Map,可以按如下方式调整代码:

  1. 实现自定义反序列化器
public class CustomMapDeserializer extends StdDeserializer<HashMap<String, Integer>> {
    public CustomMapDeserializer() {
        super(HashMap.class);
    }

    @Override
    public HashMap<String, Integer> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        HashMap<String, Integer> result = new HashMap<>();
        JsonNode arrayNode = p.getCodec().readTree(p);
        for (JsonNode item : arrayNode) {
            result.put(item.get("c").asText(), item.get("b").asInt());
        }
        return result;
    }
}
  1. 注册反序列化器并使用
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
// 第一个参数传入HashMap的Class对象
simpleModule.addDeserializer(HashMap.class, new CustomMapDeserializer());
objectMapper.registerModule(simpleModule);

// 直接反序列化得到目标Map
HashMap<String, Integer> result = objectMapper.readValue(jsonStr, new TypeReference<HashMap<String, Integer>>() {});

注意:该方案会全局修改该ObjectMapper实例对HashMap类型的反序列化逻辑,如果你有其他正常反序列化HashMap的需求,不推荐使用该方案。


内容的提问来源于stack exchange,提问作者Martin Nöbel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:06:04