You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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方法:

  1. 创建Mixin抽象类:
public abstract class XMLGregorianCalendarMixin {
    // 根据业务需求选择忽略其中一个方法,这里忽略BigInteger参数的版本
    @JsonIgnore
    public abstract void setYear(BigInteger year);
}
  1. 注册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的解析逻辑,绕开自动属性映射的冲突:

  1. 实现自定义反序列化器:
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);
        }
    }
}
  1. 注册到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,从根源避免冲突:

  1. 修改POJO字段:
@XmlElement(name = "FechaCreacion", required = true)
@XmlSchemaType(name = "dateTime")
protected LocalDateTime fechaCreacion;
  1. 配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:48:19