У меня есть служба весеннего отдыха, которая принимает и выдает json выходные данные.
@PostMapping(path = "/path", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<RequestData> method(@RequestBody RequestData request){
return request;
}
RequestData содержит несколько дат (XMLGregorianCalendar). Я не могу изменить тип, так как он генерируется из xsd. Чтобы получить даты с исходными часовыми поясами, я использовал параметр spring.jackson.date-format: yyyy-MM-dd'T'HH: мм: ссЗ
Запрос
{
"date1":"2020-02-28T09:26:59+09:00",
"date2":"2020-01-10T12:46:29+04:00",
"date3":"2020-03-15T11:32:43+08:00"
}
Из этого запроса я получил XMLGregorianCalendar с разными часовыми поясами. Но при отправке ответного сообщения даты конвертируются в 0 часовых поясов. Ответ
{
"date1":"2020-02-28T00:26:59+0000",
"date2":"2020-01-10T08:46:29+0000",
"date3":"2020-03-15T03:32:43+0000"
}
Какие настройки необходимо выполнить для Джексона, чтобы получить ненулевые часовые пояса в ответе? Необходимо, чтобы ответные часовые пояса возвращались в запросе. Или, может быть, Джексон не знает, как это сделать, и всегда конвертирует дату в один часовой пояс? В таком случае, какую библиотеку использовать? Спасибо!
Решение
Необходимо создать сериализатор и десериализатор. Затем вам нужно переопределить существующий ObjectMapper. Если переопределен только сериализатор, то после получения данных часовой пояс будет нормализован (уменьшен до +00: 00), поэтому также необходимо переопределить десериализатор. Сериализатор:
public class XMLGCSerializer extends JsonSerializer<XMLGregorianCalendar> {
@Override
public void serialize(XMLGregorianCalendar value,
JsonGenerator gen,
SerializerProvider serializers)
throws IOException {
gen.writeObject(value.toString());
}
}
Десериализатор:
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
}
}
}
Переопределить 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;
}
}