Spring Boot基于注解的XML编组:移除多余feed包装元素
解决Spring Boot XML响应多余
<feed>嵌套的问题 在Spring Boot应用中,定义了Feed和Feeds两个DTO类,通过JacksonCustomizer启用JaxbAnnotationModule后,REST API返回的XML结构中多了一层<feed>包装元素,不符合预期结构。
相关代码
DTO类
@Data public class Feed { private int id; private String name; private String title; @Builder @XmlRootElement(name = "feeds") public static class Feeds { @XmlElement(name = "feed") @Singular private List<Feed> feeds; } }
配置类
@Component public class JacksonCustomizer implements Jackson2ObjectMapperBuilderCustomizer { @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { jacksonObjectMapperBuilder.modulesToInstall(new JaxbAnnotationModule()); } }
DAO实现
public Feeds getAll() { String sqlQuery = "SELECT * FROM feed WHERE trash = 0"; return Feeds.builder().feeds(namedParameterJdbcTemplate.query(sqlQuery, new BeanPropertyRowMapper<>(Feed.class))).build(); }
当前错误XML响应
<feeds> <feed> <feed> <id>1</id> <name>Val1</name> <title>Title1</title> </feed> <feed> <id>2</id> <name>Val2</name> <title>Title2</title> </feed> </feed> </feeds>
期望XML响应
<feeds> <feed> <id>1</id> <name>Val1</name> <title>Title1</title> </feed> <feed> <id>2</id> <name>Val2</name> <title>Title2</title> </feed> </feeds>
问题原因
问题出在JAXB注解与Jackson序列化的配合逻辑上:Feeds类中的feeds字段标注了@XmlElement(name="feed"),Jackson会将这个集合字段本身序列化为一个<feed>元素,再把集合内的每个Feed对象也序列化为<feed>元素,从而产生了多余的嵌套层级。
解决方案
以下两种方式任选其一即可:
方式一:改用Jackson原生XML注解
移除JAXB注解,使用Jackson专门的XML注解控制序列化行为,明确禁用集合的外层包装:
@Data public class Feed { private int id; private String name; private String title; @Builder @JacksonXmlRootElement(localName = "feeds") public static class Feeds { @JacksonXmlProperty(localName = "feed") @JacksonXmlElementWrapper(useWrapping = false) @Singular private List<Feed> feeds; } }
如果不需要其他JAXB注解支持,可以同时移除JacksonCustomizer中的JaxbAnnotationModule配置。
方式二:调整JAXB注解配置
若坚持使用JAXB注解,需给Feed类添加@XmlType注解,并调整Feeds类的注解配置:
@Data @XmlType(name = "") // 避免Feed类生成额外的外层元素 public class Feed { private int id; private String name; private String title; @Builder @XmlRootElement(name = "feeds") @XmlAccessorType(XmlAccessType.FIELD) public static class Feeds { @XmlElement(name = "feed") @Singular private List<Feed> feeds; } }
@XmlAccessorType(XmlAccessType.FIELD)确保Jackson直接通过字段处理注解,避免潜在冲突;@XmlType(name = "")则让Feed对象序列化时不会生成额外的外层<feed>元素。
验证结果
修改完成后重启应用,调用REST API即可得到预期的XML结构,多余的<feed>嵌套会被移除。
内容的提问来源于stack exchange,提问作者Harsh Kanakhara
相关产品推荐
相关产品推荐

