在我的场景中,我正在使用XStream,我需要能够以不同的变体存储/解析相同的数据。
考虑以下课程:
用户:
public class User implements Serializable
{
@XStreamAlias(value = "roles")
private List<Role> roles = new ArrayList<Role>();
...
}
作用:
public class Role implements Serializable
{
@XStreamAlias(value = "name")
private String name;
@XStreamAlias(value = "description")
private String description;
...
}
我需要能够产生以下输出:
users.xml中
<users>
<user>
<username>admin</username>
<password>password</password>
<roles>
<role>administrator</role>
</roles>
</user>
<user>
<username>deployer</username>
<password>password</password>
<roles>
<role>deploy</role>
</roles>
</user>
</users>
roles.xml:
<roles>
<role>
<name>admin<name>
<description>Administrative role</description?
</role>
<role>
<name>deploy<name>
<description>Deployment role</description?
</role>
...
</roles>
但是,我坚持:
<users>
<user>
<username>admin</username>
<password>password</password>
<roles>
<role>
<name>admin</name>
</role>
</roles>
</user>
<user>
<username>deployer</username>
<password>password</password>
<roles>
<role>
<name>deploy</name>
</role>
<role>
<name>read</name>
</role>
<role>
<name>delete</name>
</role>
</roles>
</user>
</users>
...然而,我想得到:
<users>
...
<user>
<username>deployer</username>
<password>password</password>
<roles>
<role>
<name>deploy</name>
<name>read</name>
<name>delete</name>
</role>
</roles>
</user>
...
</users>
这是可以理解的。 User
DTO中的数据结构不同。所以,我想我需要一个Converter
。所以,我敲了下面的内容:
public class RoleListConverter
implements Converter
{
public boolean canConvert(Class clazz)
{
return AbstractList.class.isAssignableFrom(clazz);
}
public void marshal(Object value,
HierarchicalStreamWriter writer,
MarshallingContext context)
{
if (value instanceof List)
{
//noinspection unchecked
List<Role> roles = (List<Role>) value;
for (Role role : roles)
{
writer.startNode("role");
writer.setValue(role.getName());
writer.endNode();
}
}
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context)
{
List<Role> roles = new ArrayList<Role>();
while (reader.hasMoreChildren())
{
reader.moveDown();
Role role = new Role();
final String nodeName = reader.getNodeName();
if (nodeName.equals("role"))
{
role.setName(reader.getValue().trim());
roles.add(role);
}
reader.moveUp();
}
return roles;
}
}
我的解析器类看起来像这样:
public class UserParser
extends GenericParser<User>
{
...
public XStream getXStreamInstance()
{
XStream xstream = new XStream();
xstream.autodetectAnnotations(true);
xstream.alias("user", User.class);
xstream.alias("users", List.class);
xstream.alias("role", Role.class);
xstream.alias("credentials", Credentials.class);
xstream.registerConverter(new RoleListConverter());
return xstream;
}
...
}
尝试使用以下错误存储XML时失败:
java.lang.ClassCastException: org.foo.User cannot be cast to org.foo.Role
at org.foo.RoleListConverter.marshal(RoleListConverter.java:35)
显然,当我注册这个转换器时,它试图拦截所有列表并搞砸了。我在这里做错了什么以及如何实现我的目标?
提前致谢!
答案 0 :(得分:1)
回答可能有点迟了...... 无论如何。
您可以定义
private class UserList extends ArrayList<User> {};
private class RoleList extends ArrayList<Role> {};
xstream.alias("users", UserList.class);
xstream.alias("roles", RoleList.class);