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)?
Advertisement
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
.