Jackson - 仅覆盖特定字段的自定义序列化程序

2022-09-02 09:30:40

我知道如何在 Jackson 中使用自定义序列化程序(通过扩展 ),但我希望默认序列化程序适用于所有字段,除了 1 个字段,我想使用自定义序列化程序覆盖它。JsonSerializer

注释不是一个选项,因为我正在序列化一个生成的类(来自Thrift)。

如何仅指定在编写自定义 jackson 序列化程序时要覆盖的某些字段?

更新:

下面是我要序列化的类:

class Student {
    int age;
    String firstName;
    String lastName;
    double average;
    int numSubjects

    // .. more such properties ...
}

上面的类有许多属性,其中大多数使用本机类型。我只想重写自定义序列化程序中的一些属性,并让 Jackson 像往常一样处理其余属性。例如,我只想将“年龄”字段转换为自定义输出。


答案 1

假设您的目标类是

public class Student {
    int age;
    String firstName;
    String lastName;
    double average;
    int numSubjects;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    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;
    }

    public double getAverage() {
        return average;
    }

    public void setAverage(double average) {
        this.average = average;
    }

    public int getNumSubjects() {
        return numSubjects;
    }

    public void setNumSubjects(int numSubjects) {
        this.numSubjects = numSubjects;
    }

}

您需要编写自定义序列化程序,如下所示

public class MyCustomSerializer extends JsonSerializer<Student> {

    @Override
    public void serialize(Student value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        if (value != null) {
            jgen.writeStartObject();
            jgen.writeStringField("age", "Age: " + value.getAge()); //Here a custom way to render age field is used
            jgen.writeStringField("firstName", value.getFirstName());
            jgen.writeStringField("lastName", value.getLastName());
            jgen.writeNumberField("average", value.getAverage());
            jgen.writeNumberField("numSubjects", value.getNumSubjects());
            //Write other properties
            jgen.writeEndObject();
        }
    }

}

然后将其添加到对象映射器

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("custom",
        Version.unknownVersion());
module.addSerializer(Student.class, new MyCustomSerializer());
mapper.registerModule(module);

然后像这样使用它

Student s = new Student();
s.setAge(2);
s.setAverage(3.4);
s.setFirstName("first");
s.setLastName("last");
s.setNumSubjects(3);

StringWriter sw = new StringWriter();
mapper.writeValue(sw, s);
System.out.println(sw.toString());

它将产生一个类似o / p

{“age”:“Age: 2”,“firstName”:“first”,“lastName”:“last”,“average”:3.4,“numSubjects”:3}


答案 2

仅仅因为你不能修改类并不意味着你不能使用注释:只需使用混合注释。例如,请参阅博客文章(或Google以获取更多带有“jackson mixin注释”的信息)以获取有关如何使用它的信息。

我专门将Jackson与protobuf和thrift生成的类一起使用,它们工作得很好。对于早期的 Thrift 版本,我不得不禁用“is-setters”的发现,Thrift 生成的方法以查看是否已显式设置了特定属性,但除此之外,一切正常。