作者:黄少存,叩丁狼高级讲师。原创文章,转载请注明出处。
上一节咱们已经学习了一个快速的案例,从快速开始的例子上我们也知道XStream 的默认生成模式如下,
1 类的全限定名作为 xml 的跟标签
2 类的属性名作为子标签的名称
3 属性值作为标签的内容
而默认生成我们可能存在以下疑问或者迫切想知道如何处理的一些问题
1 得到xml后模型包名不同怎么办,如何解析xml?
2 如何用一个单词来表示根标签,而不是用类的全限定名?
3 如何生成 xml 属性?
4 如何处理不想生成 xml 标签的字段?
5 如何修改属性名对应的xml标签名称?
接下来咱就围绕以上几个问题来学习 XStream 处理API
修改包名
xml作为数据传递使用,当咱们获取到别人通过网络传递过来的xml数据时,如果xml没有做特殊处理,咱们得到的xml是加了别人类的全限定名的,如何将全限定名改为咱们自己的呢?操作如下
xStream.aliasPackage(“新报名”, “要替换的包名”);
模型类
@Getter
@Setter
@ToString
@NoArgsConstructor
public class User {
private Long id;
private String username;
private Integer age;
private List<Role> roles = new ArrayList<>();
public User(Long id, String username, Integer age) {
this.id = id;
this.username = username;
this.age = age;
}
}
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
class Role {
private Long id;
private String name;
}
测试类
public void testAlias() throws Exception {
XStream xStream = new XStream(new StaxDriver());
User user = new User(1L, "willie",18);
List<Role> roles2 = user.getRoles();
roles2.add(new Role(1L, "管理员"));
roles2.add(new Role(2L, "业务员"));
// 对象转入xml
String xml = xStream.toXML(user);
System.out.println(xml);
// 同步 xml 字符串到xml文件中
TransformerUtil.transform(xml,new File("user.xml"));
}
改包名设置之前生成的 xml 如下
<?xml version="1.0" encoding="UTF-8"?>
<cn.wolfcode.xstream.__02__alias.User>
<id>1</id>
<username>willie</username>
<age>18</age>
<roles>
<cn.wolfcode.xstream.__02__alias.Role>
<id>1</id>
<name>管理员</name>
</cn.wolfcode.xstream.__02__alias.Role>
<cn.wolfcode.xstream.__02__alias.Role>
<id>2</id>
<name>业务员</name>
</cn.wolfcode.xstream.__02__alias.Role>
</roles>
</cn.wolfcode.xstream.__02__alias.User>
测试类设置自定义包名
xStream.aliasPackage("cn.wolfcode.xstream", "cn.wolfcode.xstream._02_alias");
生成的xml
<?xml version="1.0" encoding="UTF-8"?>
<cn.wolfcode.xstream.User>
<id>1</id>
<username>willie</username>
<age>18</age>
<roles>
<cn.wolfcode.xstream.Role>
<id>1</id>
<name>管理员</name>
</cn.wolfcode.xstream.Role>
<cn.wolfcode.xstream.Role>
<id>2</id>
<name>业务员</name>
</cn.wolfcode.xstream.Role>
</roles>
</cn.wolfcode.xstream.User>
以上,咱们明显可以看的出来全限定名改了,但是如果我们不想要全限定名,只想使用一个简单单词来做为标签名怎么处理?请看自定义类标签
自定义类标签
从咱们对xml的书写习惯上来说,咱们更习惯使用一个普通的单词来作为标签,而在XStream中使用了类的全限定名来作为标签,如果我们想要使用简单单词表示就需要使用 XStream 对象的一个alias方法来自定义类标签的名称.
XStream对象.alias(“别名”, 类的字节码对象);
测试类设置自定义类的别名
XStream xStream = new XStream(new StaxDriver());
xStream.alias("user", User.class);
xStream.alias("role", Role.class);
生成的xml如下
<?xml version="1.0" encoding="UTF-8"?>
<user>
<id>1</id>
<username>willie</username>
<age>18</age>
<roles>
<role>
<id>1</id>
<name>管理员</name>
</role>
<role>
<id>2</id>
<name>业务员</name>
</role>
</roles>
</user>
通过以上生成的xml我们已经知道如何修改类对应的标签,但是从xml上我们也知道,id作为用户的唯一标识,其实可以作为user标签的属性,那如果我们想把id作为user标签的属性又改如何操作呢?请看以下属性设置.
属性设置
如果我们想为xml标签设置属性那需要怎么操作呢?我们都知道作为普通JavaBean的元素.有的就是成对的属性和属性值,所以接下的操作就是把属性和属性值转为xml中标签的属性.
xStream对象.useAttributeFor(要添加属性的类型, 属性字段名);
操作如下
xStream.useAttributeFor(User.class,"id");
xStream.useAttributeFor(Role.class,"id");
生成的xml如下
<?xml version="1.0" encoding="UTF-8"?>
<user id="1">
<username>willie</username>
<age>18</age>
<roles>
<role id="1">
<name>管理员</name>
</role>
<role id="2">
<name>业务员</name>
</role>
</roles>
</user>
以上 xml 我们知道, XStream 将角色集合属性生成了一个roles标签,而集合的元素则作为子元素存在,如果我们想直接生成多个role标签而不需要roles标签,那要怎么处理?请看以下隐藏集合数组标签
隐藏集合数组标签
如果只想生成集合数组的元素到xml中而不想要属性对应的标签,可使用以下隐藏处理
xstream.addImplicitCollection(集合所在类, 集合的属性名);
设置如下
xstream.addImplicitCollection(User.class, "roles");
生成的xml
<?xml version="1.0" encoding="UTF-8"?>
<user id="1">
<username>willie</username>
<age>18</age>
<role id="1">
<name>管理员</name>
</role>
<role id="2">
<name>业务员</name>
</role>
</user>
以上xml咱们明显可以看出roles标签就不再存在.但是如果咱们还想修改属性生成的对应标签怎么搞?请看对象属性标签名修改
对象属性标签名修改
可能有这样的需求咱们需要修改对象中的属性名对应的标签名称,或者咱们得到的xml中的标签名和咱们要转化成对象类型中的字段名是不一样的,但又不能修改JavaBean的字段.那修改映射标签名就可以完美的解决现在这个问题.操作如下
xstream.aliasField(“别名”, 修改的属性所在的类型, “属性名”);
设置如下
xstream.aliasField("name", User.class, "username");
生成的xml如下
<?xml version="1.0" encoding="UTF-8"?>
<user id="1">
<name>willie</name>
<age>18</age>
<role id="1">
<name>管理员</name>
</role>
<role id="2">
<name>业务员</name>
</role>
</user>
以上咱们解决了之前遗留下来的几个问题.接下咱们把完整的例子贴出来观摩下.
完整例子
@Test
public void testAlias() throws Exception {
XStream xStream = new XStream(new StaxDriver());
// 自定义包名
xStream.aliasPackage("cn.wolfcode.xstream", "cn.wolfcode.xstream._02_alias");
// 修改类对应的标签名
xStream.alias("user", User.class);
xStream.alias("role", Role.class);
// 将字段作为某个类型标签的属性
xStream.useAttributeFor(User.class,"id");
xStream.useAttributeFor(Role.class,"id");
// 隐藏集合属性生成的标签
xStream.addImplicitCollection(User.class, "roles");
// 修改属性对应标签名
xStream.aliasField("name", User.class, "username");
User user = new User(1L, "willie",18);
List<Role> roles2 = user.getRoles();
roles2.add(new Role(1L, "管理员"));
roles2.add(new Role(2L, "业务员"));
// 对象转入xml
String xml = xStream.toXML(user);
System.out.println(xml);
// 同步 xml 字符串到xml文件中
transform(xml,new File("user.xml"));
User u = (User)xStream.fromXML(xml);
System.out.println(u);
}
以上XStream 自定义生成标签操作咱们就学完了,不过通过代码咱们也可以发现,其实每次解析都需要调用如此多的方法,而且这些方法仅仅就是在改名或者加属性.跟实际对象和xml转化的核心业务是混在一起.那有没有更好的方法来处理呢?看到这里相信大家都猜到了,有更好的办法来解决,下一节咱就要来介绍下使用注解的方式来处理别名等操作.
喜欢的童鞋欢迎收藏点赞.有疑惑可在评论区发表讨论.