Spring Boot响应结果同时支持json和xml,Java Bean对象列表与xml互转

https://blog.chuangzhi8.cn/2018/07/13/ring-Boot响应结果同时支持json和xml,Java-Bean对象列表与xml互转/#more

虽然目前接口都流行响应json格式数据,但平时开发还是免不了有返回xml格式数据的需求,遇到这种情况自己写个xml解析&转换器显然太明智了,对于使用SpringBoot开发的小伙伴儿还是挺幸福的,SpringBoot已经完美支持这两种格式的解析和转换。
对于@RestController 默认支持返回json格式数据,即使不做任何配置也能返回json数据,但是返回xml格式的数据该怎么做?

1
2
3
4
5
6
7
@RestController
public class DemoController {
    @RequestMapping(value = "/query",  produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
    public Object demo() {
        
    }
}

 

然后通过query.json或者query.xml分别获取json和xml数据(不能通过设置Content-Type头为application/json或application/xml访问)
说明:网上搜的一些关于SpringBoot返回xml格式的教程都要加jackson-dataformat-xml的依赖,但是作者没有引入这个依赖依然正常使用
话外音:SpringBoot默认使用JAXB进行JavaBean和xml之间的转换。JAXB(Java Architecture for XML Binding)是根据XML Schema映射到JavaBean的技术。过程中,JAXB将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到 XML实例文档。

1
2
3
4
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

 


接下来是Java Bean与xml怎样使用注解进行互转,尤其使用对象列表时如何优雅的使用注解转成xml呢?
先给出目标xml格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BandWidthData>
    <Result>success</Result>
    <DetailInfo>expired 136 milliseconds.</DetailInfo>
    <ChannelGroupIDs>
        <ChannelGroupID ID="70813" Value="2180053898">
            <Region Name="9050" Value="2180053898"/>
            <Region Name="10200" Value="0"/>
        </ChannelGroupID>
        <ChannelGroupID ID="2539" Value="485842">
            <Region Name="9050" Value="485842"/>
            <Region Name="10200" Value="0"/>
        </ChannelGroupID>
    </ChannelGroupIDs>
</BandWidthData>

 

这个xml的结构有个较难的点就是如何使用注解表示这个ChannelGroupIDs列表?
先给出对应的Java Bean再解释各个注解的作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
最外层对象:
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) //返回xml格式时非必须,此注解是转json的蛇形命名用的
@XmlRootElement(name = "BandWidthData") // 定义xml根节点
@XmlType(propOrder = { "result", "detailInfo", "channelGroupBandwiths" }) // 定义xml节点的顺序
public class BandwidthDataResult {

    private String result;
    private List<ChannelGroupBandwithResult> channelGroupBandwiths;
    private String detailInfo;
    public String getResult() {
        return result;
    }

    @XmlElement(name = "Result") //定义xml节点
    public void setResult(String result) {
        this.result = result;
    }

    public List<ChannelGroupBandwithResult> getChannelGroupBandwiths() {
        return channelGroupBandwiths;
    }

    @XmlElementWrapper(name = "ChannelGroupIDs") // 定义list包装层节点的名称
    @XmlElement(name = "ChannelGroupID") // 映射List中每个节点的名称
    public void setChannelGroupBandwiths(List<ChannelGroupBandwithResult> channelGroupBandwiths) {
        this.channelGroupBandwiths = channelGroupBandwiths;
    }

    public String getDetailInfo() {
        return detailInfo;
    }

    @XmlElement(name = "DetailInfo")
    public void setDetailInfo(String detailInfo) {
        this.detailInfo = detailInfo;
    }
}

中间对象:
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@XmlType(propOrder = { "channelGroupId", "channelGroupBandwith", "regionBandwiths" })
public class ChannelGroupBandwithResult {
    private long channelGroupId;
    private long channelGroupBandwith;
    private List<RegionBandwithResult> regionBandwiths;

    public long getChannelGroupId() {
        return channelGroupId;
    }

    @XmlAttribute(name = "ID") // 映射将该对象的此属性为xml节点的属性
    public void setChannelGroupId(long channelGroupId) {
        this.channelGroupId = channelGroupId;
    }

    public long getChannelGroupBandwith() {
        return channelGroupBandwith;
    }

    @XmlAttribute(name = "Value") // 同上
    public void setChannelGroupBandwith(long channelGroupBandwith) {
        this.channelGroupBandwith = channelGroupBandwith;
    }


    public List<RegionBandwithResult> getRegionBandwiths() {
        return regionBandwiths;
    }

    @XmlElement(name = "Region")
    public void setRegionBandwiths(List<RegionBandwithResult> regionBandwithResults) {
        this.regionBandwiths = regionBandwithResults;
    }
}

底层对象:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@XmlType(propOrder = { "regionName", "regionBandwith" })
public class RegionBandwithResult {
    private String regionName;
    private long regionBandwith;

    public String getRegionName() {
        return regionName;
    }

    @XmlAttribute(name = "Name")
    public void setRegionName(String regionName) {
        this.regionName = regionName;
    }

    public long getRegionBandwith() {
        return regionBandwith;
    }

    @XmlAttribute(name = "Value")
    public void setRegionBandwith(long regionBandwith) {
        this.regionBandwith = regionBandwith;
    }
}

 

至此基本可以支持Java Bean的List对象转xml格式了。
采坑记录:1、作者最初使用lombok的@Setter、@Getter生成bean的set和get方法,同时把@XmlAttribute(name = “Name”)注解标在属性上,导致别名name=”Name”失效了;2、xml的相关注解不要同时在set和get方法上使用。
其他注解:1、@XmlValue 映射List中对象的属性 到 xml节点的值,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
目标接收xml格式数据:
<?xml version="1.0" encoding="GB2312"?>
<BandWidthDatas>
    <Result>success</Result>
    <Datas>
        <Data area="9050" chlgrp="10018487" >47870270,</Data>
        <Data area="10200" chlgrp="10018487" >0,</Data>
        <Data area="9050" chlgrp="33755" >6460458,</Data>
        <Data area="10200" chlgrp="33755" >0,</Data>
    </Datas>
</BandWidthDatas>

Java类的最外层对象结构:
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "BandWidthDatas")
public class BandWidthDataDTO {

    private String result;

    private List<BandWidthDetailDataDTO> datas;

    @XmlElement(name = "Result")
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    @XmlElementWrapper(name = "Datas")
    @XmlElement(name = "Data")
    public List<BandWidthDetailDataDTO> getDatas() {
        return datas;
    }

    public void setDatas(List<BandWidthDetailDataDTO> datas) {
        this.datas = datas;
    }
}

Java类最底层对象结构:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;

public class BandWidthDetailDataDTO {
    private String area;
    private String chlgrp;
    private String value;

    @XmlAttribute(name = "area")
    public String getArea() {
        return area;
    }

    public void setArea(String area) {
        this.area = area;
    }

    @XmlAttribute(name = "chlgrp")
    public String getChlgrp() {
        return chlgrp;
    }

    public void setChlgrp(String chlgrp) {
        this.chlgrp = chlgrp;
    }

    @XmlValue // 映射xml节点的值
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值