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字段,步骤如下:
- 自定义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(); } }
- 在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
相关产品推荐
相关产品推荐

