Spring Boot MVC接口JSON返回正常,XML返回失败求助
从日志警告可以明确核心问题:Jackson XML序列化时属性名冲突。OpenAPI Generator生成的模型类(如TestResponseXml、ErrorResponse)中,属性(如id、code)同时存在多个显式名称定义({}id和id),再加上隐式的setter访问器,导致Jackson无法确定使用哪个属性名进行XML序列化,最终引发HttpMediaTypeNotAcceptableException和HttpMessageNotWritableException。
这种冲突是因为启用withXml=true后,Generator同时生成了@JsonProperty(用于JSON序列化)和@JacksonXmlProperty(用于XML序列化)注解,Jackson XML模块对这两个注解的处理产生了歧义。
以下是几种可行的解决思路,按优先级排序:
1. 调整OpenAPI Generator配置,避免生成冲突注解
修改Gradle任务的configOptions,添加配置让Generator只生成Jackson XML所需的注解,消除与JSON注解的冲突:
tasks.register('openApiGenerateServer', GenerateTask) { // 原有配置保留 configOptions = [ dateLibrary : 'java8', serializationLibrary: 'jackson', library : 'spring-boot', useBeanValidation : 'true', interfaceOnly : 'true', serializableModel : 'true', useTags : 'true', sourceFolder : 'src/main/java', testFolder : 'src/test/java', useSpringBoot3 : 'true', openApiNullable : 'true', withXml : 'true', // 添加以下配置 xmlAnnotations : 'jackson', useJacksonXmlAnnotation: 'true' ] }
重新生成代码后,模型类只会包含@JacksonXmlProperty注解,彻底消除属性名冲突。
2. 自定义Jackson XmlMapper,解决序列化歧义
如果无法修改Generator配置,可通过自定义XmlMapper强制忽略冲突:
创建Spring配置类:
import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; @Configuration public class XmlSerializationConfig { @Bean public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter() { XmlMapper xmlMapper = XmlMapper.builder() // 禁用隐式属性访问器推断,只使用显式注解 .disable(MapperFeature.INFER_PROPERTY_MUTATORS) // 仅识别Jackson XML专属注解 .annotationIntrospector(new com.fasterxml.jackson.dataformat.xml.JacksonXmlAnnotationIntrospector()) .propertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE) .build(); return new MappingJackson2XmlHttpMessageConverter(xmlMapper); } }
该配置会让XML序列化只处理@JacksonXmlProperty注解,忽略隐式setter带来的属性名歧义。
3. 调整OpenAPI Schema定义,明确XML属性名
在springtest.yaml中,为每个需要XML序列化的属性显式指定XML名称,确保Generator生成的注解一致:
components: schemas: TestResponseXml: type: object properties: id: type: integer xml: name: id ErrorResponse: type: object properties: code: type: integer xml: name: code
显式的XML名称定义会让Generator生成更准确的@JacksonXmlProperty注解,减少歧义概率。
重新启动项目后,调用XML接口,检查日志是否还有属性名冲突警告,同时确认接口能正常返回XML格式响应。
内容的提问来源于stack exchange,提问作者vkourt

