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

Jackson序列化Map<Object, Object>:如何用C类ID作为Map序列化键?

解决Jackson序列化Map时使用C类ID作为键的问题

看起来你遇到了Jackson序列化Map<A, C>时,默认用A对象的toString值(比如com.project.model.A@5abbb6ce)作为键的问题,想要把键替换成对应C对象的id对吧?下面给你两种解决方案,一种是针对你明确提出的用C的id作为键,另一种是更常见的用A的id作为键的情况(以防你是笔误)。

一、使用C类的ID作为Map的键序列化

因为你的Map是Map<A, C>,键是A实例,值是对应的C实例,要把键换成C的id,需要自定义一个序列化器来处理这个Map字段,步骤如下:

  1. 自定义Map序列化器
    创建一个继承自StdSerializer<Map<A, C>>的序列化器,在序列化时把原Map转换成以C的id为键的新Map结构:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Map;

public class AToCIdMapSerializer extends StdSerializer<Map<A, C>> {

    protected AToCIdMapSerializer() {
        super((Class<Map<A, C>>) (Class<?>) Map.class);
    }

    @Override
    public void serialize(Map<A, C> map, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        for (Map.Entry<A, C> entry : map.entrySet()) {
            C cInstance = entry.getValue();
            // 用C实例的id作为键,序列化对应的C对象内容
            gen.writeObjectField(String.valueOf(cInstance.getId()), cInstance);
        }
        gen.writeEndObject();
    }
}
  1. 在B类的map字段上指定序列化器
    在B类的map字段上添加@JsonSerialize注解,指定刚才自定义的序列化器:
public class B { 
    @Id private Integer id; 
    @JsonSerialize(using = AToCIdMapSerializer.class)
    private Map<A, C> map; 
    // 请补充getter、setter方法
}

这样序列化B实例后,map的键就会变成对应C对象的id,结果类似:

{ 
    "id":52, 
    "map":{ 
        "12":{ "id":12, "object":"some string" }, 
        "15":{ "id":15, "object":"another string" } 
    } 
}

二、更常见的场景:使用A类的ID作为Map的键序列化

如果你其实是想把Map的键换成A对象的id(这是实体类作为Map键时的常规需求),可以用更简洁的方式实现:

方法1:使用@JsonKey注解(Jackson 2.13+版本支持)

从Jackson 2.13版本开始,你可以直接在A类的id字段上添加@JsonKey注解,指定该字段作为Map键的序列化值:

public class A { 
    @Id 
    @JsonKey
    private Integer id; 
    private String value; 
    // 请补充getter、setter方法
}

方法2:自定义KeySerializer(兼容低版本Jackson)

如果你的Jackson版本低于2.13,可以自定义一个KeySerializer来处理A对象的键序列化:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;

public class AKeySerializer extends StdSerializer<A> {

    protected AKeySerializer() {
        super(A.class);
    }

    @Override
    public void serialize(A aInstance, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 用A实例的id作为Map的键
        gen.writeFieldName(String.valueOf(aInstance.getId()));
    }
}

然后在A类上添加注解,指定这个键序列化器:

@JsonSerialize(keyUsing = AKeySerializer.class)
public class A { 
    @Id private Integer id; 
    private String value; 
    // 请补充getter、setter方法
}

这样序列化后,map的键就会变成A对象的id,结果类似:

{ 
    "id":52, 
    "map":{ 
        "101":{ "id":12, "object":"some string" }, 
        "102":{ "id":15, "object":"another string" } 
    } 
}

(注:101、102对应A对象的实际id值)


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:50:57