Jackson-更改映射密钥名称而无需自定义序列化器

时间:2018-06-28 22:23:17

标签: java serialization jackson

在使用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有一个注释可以做到这一点,但似乎找不到它。

1 个答案:

答案 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那样向对象映射器注册。