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

    com.fasterxml.jackson.dataformat
    jackson-dataformat-xml

 


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


    success
    expired 136 milliseconds.
    
        
            
            
        
        
            
            
        
    

 

这个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 channelGroupBandwiths;
    private String detailInfo;
    public String getResult() {
        return result;
    }

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

    public List getChannelGroupBandwiths() {
        return channelGroupBandwiths;
    }

    @XmlElementWrapper(name = "ChannelGroupIDs") // 定义list包装层节点的名称
    @XmlElement(name = "ChannelGroupID") // 映射List中每个节点的名称
    public void setChannelGroupBandwiths(List 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 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 getRegionBandwiths() {
        return regionBandwiths;
    }

    @XmlElement(name = "Region")
    public void setRegionBandwiths(List 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格式数据:


    success
    
        47870270,
        0,
        6460458,
        0,
    


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 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 getDatas() {
        return datas;
    }

    public void setDatas(List 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;
    }
}

 

你可能感兴趣的:(spring,boot)