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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:16:47