I have a spring rest service that accepts and gives json output.
@PostMapping(path = "/path", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<RequestData> method(@RequestBody RequestData request){
return request;
}
RequestData contains several dates (XMLGregorianCalendar). I cannot change the type, since it is generated from xsd. To get dates with the original time zones, I used the parameter spring.jackson.date-format: yyyy-MM-dd'T'HH:mm:ssZ
Request
{
"date1":"2020-02-28T09:26:59+09:00",
"date2":"2020-01-10T12:46:29+04:00",
"date3":"2020-03-15T11:32:43+08:00"
}
From this request, I got an XMLGregorianCalendar with different time zones. But when sending a response message, the dates are converted to 0 time zone. Response
{
"date1":"2020-02-28T00:26:59+0000",
"date2":"2020-01-10T08:46:29+0000",
"date3":"2020-03-15T03:32:43+0000"
}
What settings need to be done on jackson to get non-zero time zones in the response? It is necessary that the response time zones returned in the request. Or maybe jackson does not know how to do this and always converts the date to a single time zone? In that case, which library to use? Thanks!
Solution
You must create a serializer and deserializer. Then you need to override the existing ObjectMapper. If only the serializer is overrided, then upon receipt of the data, the time zone will be normalized (reduced to +00:00), therefore it is also necessary to override the deserializer. Serializer:
public class XMLGCSerializer extends JsonSerializer<XMLGregorianCalendar> {
@Override
public void serialize(XMLGregorianCalendar value,
JsonGenerator gen,
SerializerProvider serializers)
throws IOException {
gen.writeObject(value.toString());
}
}
Deserializer:
public class XMLGCDeserializer extends JsonDeserializer<XMLGregorianCalendar> {
@Override
public XMLGregorianCalendar deserialize(JsonParser parser, DeserializationContext context) throws IOException {
String stringDate = parser.getText();
try {
return DatatypeFactory.newInstance().newXMLGregorianCalendar(stringDate);
} catch (Exception e) {
throw new RuntimeException(e);
//or return null
}
}
}
Override ObjectMapper
@Component
public class JacksonConfig {
private final ObjectMapper objectMapper;
public JacksonConfig() {
objectMapper = new ObjectMapper();
SimpleModule s = new SimpleModule();
s.addSerializer(XMLGregorianCalendar.class, new XMLGCSerializer());
s.addDeserializer(XMLGregorianCalendar.class, new XMLGCDeserializer());
objectMapper.registerModule(s);
}
@Bean
public ObjectMapper getContext() {
return objectMapper;
}
}