XMLGregorianCalendar的year属性Setter冲突问题及解决咨询
解决XMLGregorianCalendar中year属性Setter方法冲突问题
问题根源
javax.xml.datatype.XMLGregorianCalendar类存在两个签名不同但属性名相同的setYear方法:
public abstract void setYear(BigInteger year); public abstract void setYear(int year);
这会导致Jackson(或依赖Jackson的Springfox)在解析POJO时无法确定使用哪个Setter,抛出IllegalArgumentException冲突异常。
解决方案
方案1:使用Jackson Mixin忽略冲突方法
通过Mixin类无需修改第三方类源码,即可标记忽略其中一个Setter方法:
- 创建Mixin抽象类:
public abstract class XMLGregorianCalendarMixin { // 根据业务需求选择忽略其中一个方法,这里忽略BigInteger参数的版本 @JsonIgnore public abstract void setYear(BigInteger year); }
- 注册Mixin到ObjectMapper(Spring环境可通过配置类注入):
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(XMLGregorianCalendar.class, XMLGregorianCalendarMixin.class); return mapper; } }
方案2:自定义Jackson反序列化器
完全接管XMLGregorianCalendar的解析逻辑,绕开自动属性映射的冲突:
- 实现自定义反序列化器:
public class XMLGregorianCalendarDeserializer extends StdDeserializer<XMLGregorianCalendar> { protected XMLGregorianCalendarDeserializer() { super(XMLGregorianCalendar.class); } @Override public XMLGregorianCalendar deserialize(JsonParser parser, DeserializationContext context) throws IOException { String dateStr = parser.getText(); try { DatatypeFactory dtf = DatatypeFactory.newInstance(); return dtf.newXMLGregorianCalendar(dateStr); } catch (DatatypeConfigurationException e) { throw new IOException("解析XMLGregorianCalendar失败", e); } } }
- 注册到Jackson模块:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(XMLGregorianCalendar.class, new XMLGregorianCalendarDeserializer()); mapper.registerModule(module); return mapper; } }
方案3:替换为Java 8日期API(推荐)
直接用Java 8标准日期类型(如LocalDateTime、ZonedDateTime)替换XMLGregorianCalendar,从根源避免冲突:
- 修改POJO字段:
@XmlElement(name = "FechaCreacion", required = true) @XmlSchemaType(name = "dateTime") protected LocalDateTime fechaCreacion;
- 配置Jackson支持Java 8日期类型:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); // 禁用时间戳序列化,输出ISO格式字符串 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return mapper; } }
方案4:针对SpringFox的自定义Schema处理
如果冲突仅发生在SpringFox生成API文档时,可自定义Schema解析逻辑:
@Component public class XMLGregorianCalendarSchemaHandler implements ModelBuilderPlugin { @Override public void apply(ModelContext context) { if (XMLGregorianCalendar.class.isAssignableFrom(context.getType())) { context.getBuilder() .name("DateTime") .type(new ModelRef("string")) .description("ISO 8601格式的日期时间字符串"); } } @Override public boolean supports(DocumentationType documentationType) { return true; } }
内容的提问来源于stack exchange,提问作者Alfredo Morales
相关产品推荐
相关产品推荐

