Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - custom serializer that overrides only specific fields

Tags:

I know how to use a custom serializer in Jackson (by extending JsonSerializer), but I want the default serializer to work for all fields, except for just 1 field, which I want to override using the custom serializer.

Annotations are not an option, because I am serializing a generated class (from Thrift).

How do I specify only certain fields to be overridden when writing a custom jackson serializer?

Update:

Here's the class I want to serialize:

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

    // .. more such properties ...
}

The above class has many properies, most of which use native types. I want to just override a few properties in the custom serializer and let Jackson deal with the rest as usual. For e.g. I just want to convert the "age" field to a custom output.

like image 715
jeffreyveon Avatar asked Mar 13 '13 06:03

jeffreyveon


1 Answers

Assuming your Target class is

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

}

You need to write a custom serializer as given below

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

}

then add it to the ObjectMapper

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

then use it like

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());

It will produce a o/p like

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

like image 182
Arun P Johny Avatar answered Oct 16 '22 10:10

Arun P Johny