如何在 Spring Boot Rest API 中以 XML 形式返回对象列表

Posted

技术标签:

【中文标题】如何在 Spring Boot Rest API 中以 XML 形式返回对象列表【英文标题】:How to return a list of objects as XML in Spring boot rest API 【发布时间】:2021-09-23 05:57:43 【问题描述】:

我正在编写一个 Java 网络服务,它将以以下 XML 格式返回产品列表。

    <?xml version="1.0"?>
    
    <Products>
    <Product>
        <Name>Notepad++ 6</Name>
        <PatchUid>00038b09-0000-0000-0000-000000000000</PatchUid>
        <RegID>0</RegID>
    </Product>
    <Product>
        <Name>UltraVNC 1.2.4.0 x86</Name>   
        <PatchUid>00035767-0000-0000-0000-000000000000</PatchUid>
        <RegID>0</RegID>
    </Product>
    <Product>
        <Name>FileZilla 3</Name>    
        <PatchUid>00038c69-0000-0000-0000-000000000000</PatchUid>
        <RegID>1033</RegID>
    </Product>
    </Products>

我正在使用如下所示的基于类的投影从 jdbc/hibernate 连接中获取 Name、PatchUid、RegId 标记。

public class ProductView implements Serializable 

    private static final long serialVersionUID = 1L;

    @JsonProperty("Name")
    String name;
    @JsonProperty("PatchUid")
    String patchuid;
    @JsonProperty("RegId")
    String language;

    public ProductView() 
        super();
        // TODO Auto-generated constructor stub
    

    public ProductView(String name, String patchuid, String language) 
        this.name = name;
        this.patchuid = patchuid;
        this.language = language;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getPatchuid() 
        return patchuid;
    

    public void setPatchuid(String patchuid) 
        this.patchuid = patchuid;
    

    public String getLanguage() 
        return language;
    

    public void setLanguage(String language) 
        this.language = language;
    


现在,为了返回 XML 响应,我使用下面的 DTO 类和休息控制器方法

    public class Products implements Serializable 
        
        private static final long serialVersionUID = 3639898896768313168L;
        
        
        private List<ProductView> products;
    
        public Products() 
            super();
            // TODO Auto-generated constructor stub
        
    
        public Products(List<ProductView> products) 
            this.products = products;
        
    
        public List<ProductView> getProduct() 
            return products;
        
    
        public void setProduct(List<ProductView> products) 
    
            this.products = products;
        
    
    
    
    
    @GetMapping("/patchMetadata")
    public Products getProductMetadata(@RequestParam(required=false) Boolean filtered) 
            
            logger.info("getProductMetadata called");
    
            List<ProductView> prodViews = null;
            
            if(filtered == null || filtered == false)
            
                prodViews = prodMgmtService.findAllPatches();
            
            else if (filtered == true) 
                prodViews = prodMgmtService.findFilteredPatches();
             
    
            Products products = new Products();
            products.setProduct(prodViews);
    
            return products;
    

但返回的 XML 格式如下所示。请注意需要删除的额外产品标签。

    <Products>
        <product>
            <product>
                <Name>FileZilla 3</Name>
                <PatchUid>0003931b-0000-0000-0000-000000000000</PatchUid>
                <RegId>0</RegId>
            </product>
            <product>
                <Name>Notepad++ 6</Name>
                <PatchUid>00038b09-0000-0000-0000-000000000000</PatchUid>
                <RegId>0</RegId>
            </product>
            <product>
                <Name>UltraVNC 1.2.4.0 x86</Name>
                <PatchUid>00035767-0000-0000-0000-000000000000</PatchUid>
                <RegId>0</RegId>
            </product>
        </product>
    </Products>

如果有任何建议可以更正从 Web 服务返回的 XML 格式,请告诉我。

【问题讨论】:

也许你可以使用响应对象来明确地写入列表。将响应对象传递给此方法使用响应流并写回列表 【参考方案1】:

不要从您的服务返回Products,而是返回List&lt;ProductView&gt;

@GetMapping("/patchMetadata")
public List<ProductView> getProductMetadata(@RequestParam(required=false) Boolean filtered) 
    List<ProductView> prodViews = null;
    if(filtered == null || filtered == false) 
        prodViews = prodMgmtService.findAllPatches();
     else if (filtered == true) 
        prodViews = prodMgmtService.findFilteredPatches();
     

    return prodViews;

【讨论】:

我已经尝试过了,我在响应中看到像 和 这样的奇怪标签,如下所示。 FileZilla 30003931b-0000-0000-0000-0000000000000Notepad++ 600038b09-0000-0000-0000-0000000000000UltraVNC 1.2。 4.0 x8600035767-0000-0000-0000-0000000000000【参考方案2】:

使用@JacksonXmlElementWrapper(useWrapping = false) 更改 Products DTO 类如下。

公共类 Products 实现 Serializable

    private static final long serialVersionUID = 3639898896768313168L;
    
    @JacksonXmlElementWrapper(useWrapping = false)
    @JsonProperty("Product")
    private List<ProductView> product;

    public Products() 
        super();
        // TODO Auto-generated constructor stub
    

    public Products(List<ProductView> products) 
        this.product = products;
    

    public List<ProductView> getProduct() 
        return product;
    

    public void setProduct(List<ProductView> products) 

        this.product = products;
    


【讨论】:

以上是关于如何在 Spring Boot Rest API 中以 XML 形式返回对象列表的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot JWT - 如何实现刷新令牌和注销 REST-API

如何在 Spring Boot REST API 中格式化返回的 json?

在 Spring-boot 中成功登录后如何限制 POST Rest Api 以供公共访问

如何在 Spring Boot Rest api 响应的 ResponseEntity 中添加自定义属性

如何在 Spring Boot Rest API 中以 XML 形式返回对象列表

如何在 Spring Boot Rest api 中创建安全登录控制器