Passing arguments to Java class used in @JsonSerialize and @JsonDeserialize



I have a scenario which I am not sure how to google, so I’d open a question myself. If its a duplicate please link it here so I can give that question credit.

Anyway,

I have a Java Object with fields that I have the following annotations:

@JsonSerialize(using = CustomSerializer.class)
@JSonDeserialize(using = CustomDeserializer.class)
private Date systemDate;

The business dictates that certain systemDate values in different database have different time zones (not sure why they did not standardize to UTC).

Here is an example of my CustomSerializer.java:

@Override
public void serialize(Date, value, JsonGenerator gen, SerializerProvider arg2) throws IOException {
    SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
    formatter.setTimeZone(TimeZone.getTimeZone("CET"));
    if (value == null) {
        gen.writeNull();
    } else {
        gen.writeString(formatter.formate(value.getTime()));
    }
}

Instead of creating a new serializer class per timezone, is there a way to pass the timezone argument(s) to this class (and also my Deserializer class)?

Answer

You need to create a custom annotation as below:

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface DateSerialize {
    String timeZone();
}

Now in the field systemDate add this new annotation by passing the timezone

@DateSerialize(timeZone = "UTC")
@JsonSerialize(using = CustomSerializer.class)
@JSonDeserialize(using = CustomDeserializer.class)
private Date systemDate;

Your serializer class should implement ContextualSerializer this would allow us to get the BeanProperty from where we could get the annotation details.

public class DateSerializer extends JsonSerializer<Date> implements ContextualSerializer {
    String timeZone;

    public DateSerializer() {
        this("UTC");
    }    
    
    public DateSerializer(String tz) {
        timeZone = tz;
    }

    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
        formatter.setTimeZone(TimeZone.getTimeZone(timeZone));
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeString(formatter.format(value.getTime()));
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { 
        DateSerialize annotation = property.getAnnotation(DateSerialize.class);
        String tz = (annotation == null) ? "UTC" : annotation.timeZone();   
        return new DateSerializer(tz);
    }
}

Similarly you could create a deserializer by implementing ContextualDeserializer.



Source: stackoverflow