Spring REST проблема часового пояса при использовании XMLGregorianCalendar - PullRequest
1 голос
/ 19 марта 2020

У меня есть служба весеннего отдыха, которая принимает и выдает 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;
    }
}

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Вы можете создать отдельный класс для самостоятельной обработки сериализации. Вот пример:

class XMLGCSerializer extends JsonSerializer<XMLGregorianCalendar> {

    @Override
    public void serialize(XMLGregorianCalendar value, 
            JsonGenerator gen, 
            SerializerProvider serializers)
            throws IOException {
        gen.writeObject(value.toString());
    }

}

Теперь вам просто нужно аннотировать свои поля в RequestData:

class RequestData{
    @JsonSerialize(using = XMLGCSerializer.class)
    XMLGregorianCalendar date1;
    //...
}
0 голосов
/ 19 марта 2020

Я думаю, что есть лучший способ сделать это. Вот ссылка на другой вопрос с очень хорошим ответом на этот вопрос: Spring Data JPA - формат ZonedDateTime для json сериализация

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...