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

如何使用Jackson将对象数组反序列化为以对象属性为键的Map

嗨,这个需求我之前也碰到过,Jackson完全能搞定,给你两种实用的方案:

方案一:自定义Json反序列化器

这种方式灵活性最高,适合后续可能有扩展需求的场景:

  1. 首先定义你的Symbol实体类:
public class Symbol {
    private String a;
    private String b;

    // 生成无参构造器、全参构造器、getter和setter方法
}
  1. 编写自定义的反序列化器,负责把JSON数组转成以a属性为键的Map:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class SymbolArrayToMapDeserializer extends JsonDeserializer<Map<String, Symbol>> {
    @Override
    public Map<String, Symbol> deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        Map<String, Symbol> symbolMap = new HashMap<>();
        // 读取JSON数组节点
        JsonNode arrayNode = parser.getCodec().readTree(parser);
        Iterator<JsonNode> elementIterator = arrayNode.elements();
        
        while (elementIterator.hasNext()) {
            // 把每个数组元素转成Symbol对象
            Symbol symbol = parser.getCodec().treeToValue(elementIterator.next(), Symbol.class);
            // 以a属性为键存入Map
            symbolMap.put(symbol.getA(), symbol);
        }
        return symbolMap;
    }
}
  1. 在MyContainer的symbols字段上标注使用这个反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Map;

public class MyContainer {
    private String name;
    
    @JsonDeserialize(using = SymbolArrayToMapDeserializer.class)
    private Map<String, Symbol> symbols;

    // 生成无参构造器、getter和setter方法
}
方案二:利用@JsonCreator工厂方法

这种方式更简洁,不需要额外写反序列化器类,适合简单场景:

直接修改MyContainer类,通过@JsonCreator标注的构造器来处理数组转Map的逻辑:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
import java.util.Arrays;
import java.util.stream.Collectors;

public class MyContainer {
    private String name;
    private Map<String, Symbol> symbols;

    // 用@JsonCreator指定Jackson使用这个构造器反序列化
    @JsonCreator
    public MyContainer(
            @JsonProperty("name") String name,
            @JsonProperty("symbols") Symbol[] symbolsArray
    ) {
        this.name = name;
        // 把数组转成Map,a属性作为键
        this.symbols = Arrays.stream(symbolsArray)
                .collect(Collectors.toMap(Symbol::getA, symbol -> symbol));
    }

    // 记得添加无参构造器(如果Jackson需要做序列化操作的话)
    public MyContainer() {}

    // 生成getter和setter方法
}

注意事项

  • 你已经保证所有Symbol的a属性值唯一,所以Collectors.toMap不会抛出DuplicateKeyException;如果后续有重复风险,可以添加第三个参数处理冲突,比如Collectors.toMap(Symbol::getA, symbol -> symbol, (oldVal, newVal) -> oldVal)
  • 两种方案都需要确保Jackson能正常反序列化Symbol类,所以类要有无参构造器,或者用全参构造器配合@JsonProperty标注

内容的提问来源于stack exchange,提问作者Edy Bourne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:12:06