在使用Person
是的Jackson来序列化Person
类时:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "My name is "+name+" ("+age+")";
}
}
我得到以下输出:
Map<Person, String> map = new HashMap<>();
Person john = new Person("John", 20);
map.put(john, "abc");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(System.out, map); //1
objectMapper.writeValue(System.out, john); //2
1:
{"My name is John (20)":"abc"}
2:
{"name":"John","age":20}
是否有一种简便的方法(没有自定义序列化器)来更改映射键以使用name
属性而不是#1中的toString
输出,而不会丢失#2中Person
对象的序列化输出,并且没有更改toString
返回值?我希望getName
有一个注释可以做到这一点,但似乎找不到它。
答案 0 :(得分:1)
自定义序列化器和addKeySerializer似乎是一种更好的方法,尽管创建模块,添加序列化器或KeySerializer并向您的映射器注册该模块有点麻烦。
如果由于某些原因(如您所述),您将无法使用自定义序列化程序。以下是一些可能对您有帮助的选项
均产生输出
{"John":"abc"}
编写地图时,但保持单个对象不变
{"name":"John","age":20}
要在输出上映射的Java 8流
与简单示例相比,取决于实际对象的复杂程度,您可能可以在writeValue调用期间或之前简单地进行映射。
mapper.writeValue(System.out,
map.entrySet().stream().collect(
Collectors.toConcurrentMap(
k -> k.getKey().getName(),
Function.identity())));
在集合上实现JsonSerializable
如果您可以将集合更改为扩展HashMap的自定义版本。
class PersonHashMap extends HashMap<Person, String> implements JsonSerializable {
@Override
public void serialize(JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
for (Entry<Person, String> e : entrySet()) {
jsonGenerator.writeStringField(e.getKey().getName(), e.getValue());
}
jsonGenerator.writeEndObject();
}
@Override
public void serializeWithType(JsonGenerator jsonGenerator, SerializerProvider serializerProvider, TypeSerializer typeSerializer) throws IOException {
.
.
.
}
}
缺点是您需要控制地图的初始化,以执行以下操作:
Map<Person, String> map = new PersonHashMap();
但是再说一遍,这就是所需要的,不需要额外的模块,也不需要像使用JsonSerializer那样向对象映射器注册。