java - 使用 XMLGregorianCalendar 时的 Spring REST 时区问题
问题描述
我有一个接受并提供 json 输出的 spring rest 服务。
@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:mm:ssZ
要求
{
"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
}
}
}
覆盖对象映射器
@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;
}
}
解决方案
您可以创建一个单独的类来自己处理序列化。这是一个例子:
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;
//...
}
推荐阅读
- php - 如何在php中删除字符串末尾附近的分配字符?
- bash - 将文件的附加数据实时复制到另一个文件
- php - PHPunit 单个 ok/failed 结果
- python - 如何运行我所有的 python 脚本抛出代理
- javascript - 为什么渲染数据不显示?
- javascript - 遍历动态的嵌套对象
- javascript - 有时会出现错误“未处理的拒绝(TypeError):无法读取未定义的属性'值'”
- c# - 如何以编程方式创建 ThemeShadow?(C# UWP 1903)
- r - R Shiny中的两个相互依赖的selectizeInput
- amazon-web-services - 从另一个 AWS API 网关调用一个 AWS API 网关的最快方法