Spring REST服务XMLGregorianCalendar时区响应转换异常解决方案
问题分析
你遇到的核心问题是:Jackson对XMLGregorianCalendar的默认序列化/反序列化逻辑会自动将时区转换为UTC,哪怕配置了spring.jackson.date-format也无效——因为这个配置仅针对普通Date类型,对XSD自动生成的XMLGregorianCalendar不生效。而且由于RequestData是生成类无法修改字段类型,必须通过自定义序列化器+反序列化器的组合方案解决,必须同时重写两者:只改序列化器的话,反序列化阶段Jackson依然会把请求中的时区标准化为UTC,导致后续响应时根本拿不到原始时区信息。
解决方案
1. 自定义XMLGregorianCalendar序列化器
直接使用XMLGregorianCalendar的toString()方法输出,该方法会保留原始的时区偏移格式:
public class XMLGCSerializer extends JsonSerializer<XMLGregorianCalendar> { @Override public void serialize(XMLGregorianCalendar value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeObject(value.toString()); } }
2. 自定义XMLGregorianCalendar反序列化器
通过DatatypeFactory直接解析请求中的日期字符串,完整保留原始时区信息:
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); // 可根据业务需求调整异常处理,比如返回null或自定义业务异常 } } }
3. 注册自定义组件到ObjectMapper
创建Spring配置类,重写默认ObjectMapper并注册自定义序列化/反序列化器:
@Component public class JacksonConfig { private final ObjectMapper objectMapper; public JacksonConfig() { objectMapper = new ObjectMapper(); SimpleModule xmlGcModule = new SimpleModule(); xmlGcModule.addSerializer(XMLGregorianCalendar.class, new XMLGCSerializer()); xmlGcModule.addDeserializer(XMLGregorianCalendar.class, new XMLGCDeserializer()); objectMapper.registerModule(xmlGcModule); } @Bean public ObjectMapper getContext() { return objectMapper; } }
验证
配置完成后重新启动服务,发送你提供的请求,响应中的日期字段会和请求中的时区完全一致,不会再被转换为UTC时区。
内容的提问来源于stack exchange,提问作者Руслан Кузнецов
相关产品推荐
相关产品推荐

