用来记录一些原创性的总结
先来看一下假设我们有如下这样结构的两个Class
定义。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class User {
private Integer id;
private String name;
@XmlElement(name="post")
private List<Post> posts;
//...省略get/set方法
}
@XmlAccessorType(XmlAccessType.FIELD)
public static class Post {
private Integer id;
private String name;
//...省略get/set方法
}
如果我们需要通过JAXB把它转换为对应的XML表示,那结果会是怎样呢?我们来看下面的测试代码及其输出结果。
@Test
public void test() {
User user = new User();
user.setId(1);
user.setName("张三");
List<Post> posts = new ArrayList<>();
for (int i=0; i<3; i++) {
Post post = new Post();
post.setId(i+1);
post.setName(String.valueOf((char)('A'+i)));
posts.add(post);
}
user.setPosts(posts);
JAXB.marshal(user, System.out);
}
上面的测试代码的输出结果如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<id>1</id>
<name>张三</name>
<post>
<id>1</id>
<name>A</name>
</post>
<post>
<id>2</id>
<name>B</name>
</post>
<post>
<id>3</id>
<name>C</name>
</post>
</user>
从上面的输出结果我们可以看到JAXB在转换对象为XML时默认会把对象中的List
类型的属性(其实不只是java.util.List
,更确切的说是java.util.Collection
)分别把其中包含的元素转换为对应的XML,且对应的根节点元素名称由List
类型的属性决定,在上面的示例中我们通过在posts
属性上加上@XmlElement(name="post")
指定了其节点名称为post
。这种输出结果是ok的,但是有时候我们可能希望post
节点不直接出现在user
节点下,而是希望可以多包一层posts
,形成user>posts>post
这样的结构。这其实很简单,我们只需要在对应的集合属性上加上XmlElementWrapper
注解,这样JAXB就会自动为我们多包一层。我们也可以通过XmlElementWrapper
的name
属性指定需要多包一层的元素的名称,不指定时默认会以对应的属性名为名。
XmlElementWrapper
不一定是加在属性上,这取决于你的XmlAccessorType
定义,像笔者的示例里面XmlAccessorType
指定的是FIELD
,所以就加在属性上。
使用XmlElementWrapper
注解标注后的代码如下:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class User {
private Integer id;
private String name;
@XmlElementWrapper(name="posts")
@XmlElement(name="post")
private List<Post> posts;
//... 省略get/set方法
}
同样运行原来的测试代码,这个时候生成的XML就是如下这样:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
<id>1</id>
<name>张三</name>
<posts>
<post>
<id>1</id>
<name>A</name>
</post>
<post>
<id>2</id>
<name>B</name>
</post>
<post>
<id>3</id>
<name>C</name>
</post>
</posts>
</user>
需要注意的是
XmlElementWrapper
只能用于标注集合类型。
(本文由Elim写于2017年6月29日)