杰克逊自定义序列化器

时间:2019-10-01 06:12:37

标签: java json jackson

可以将单个自定义序列化器用作键序列化器和普通对象序列化器吗?

即有时将序列化程序用作用于序列化地图密钥的密钥序列化程序,而有时则将对象正常序列化。

我在将JsonGenerator对象传递给序列化器方法时遇到问题。

用作键序列化程序时,它需要一个字段名,但是当正常使用时,它需要一个值。

1 个答案:

答案 0 :(得分:1)

您可以使用相同的自定义序列化器,但需要以某种方式区分是需要生成属性还是要生成整个对象。 Map被序列化为JSON Object,其中Map键被转换为JSON Object属性。要使用Jackson生成属性,我们需要使用writeFieldName方法。为了区别您想要在构造函数中使用此序列化器的方式,可以提供此信息。示例:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.util.Collections;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        SimpleModule userModule = new SimpleModule();
        userModule.addSerializer(User.class, new UserJsonSerializer(false));
        userModule.addKeySerializer(User.class, new UserJsonSerializer(true));

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(userModule);

        User user = new User();
        System.out.println(mapper.writeValueAsString(Collections.singletonMap(user, user)));
    }
}

class User {

    private String firstName = "Tom";
    private String lastName = "Smith";

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

class UserJsonSerializer extends JsonSerializer<User> {

    private final boolean generateKey;

    UserJsonSerializer(boolean generateKey) {
        this.generateKey = generateKey;
    }

    @Override
    public void serialize(User value, JsonGenerator gen, SerializerProvider serializers)
        throws IOException {
        if (generateKey) {
            serializeAsMapKey(value, gen);
        } else {
            serializeAsObject(value, gen);
        }
    }

    private void serializeAsMapKey(User value, JsonGenerator gen) throws IOException {
        gen.writeFieldName(String.join(",", value.getFirstName(), value.getLastName()));
    }

    private void serializeAsObject(User value, JsonGenerator gen) throws IOException {
        gen.writeStartObject();
        gen.writeFieldName("first");
        gen.writeString(value.getFirstName());
        gen.writeFieldName("last");
        gen.writeString(value.getLastName());
        gen.writeEndObject();
    }
}

上面的代码显示:

{
  "Tom,Smith" : {
    "first" : "Tom",
    "last" : "Smith"
  }
}

如果没有通用逻辑,则可以创建两个单独的类:UserJsonSerializerUserKeyJsonSerializer,这是一个面向对象的清晰解决方案。