我有许多的XML文档Entity
元件,其各自具有的属性type="foo"
或type="bar"
。 请参见本示例:
<RootNode>
<Entities>
<Entity type="foo">
<Price>1</Price>
</Entity>
<Entity type="bar">
<URL>www.google.co.uk</URL>
</Entity>
<Entity type="foo">
<Price>77</Price>
</Entity>
</Entities>
</RootNode>
我需要一种方法来告诉简单的反序列化Entity
的元素type="foo"
到一个List<FooEntity>
并与元素type="bar"
到一个List<BarEntity>
我怎样才能做到这一点?
这里是如果你要玩它我目前拥有的代码:
public class App {
public static void main(String[] args) throws Exception {
Reader r = Files.newBufferedReader(
Paths.get("/path/to/file.xml"),
Charset.defaultCharset()
);
Serializer serializer = new Persister();
RootNode root = serializer.read(RootNode.class, r);
System.out.println(root.getFooEntities().size());
System.out.println(root.getBarEntities().size());
}
}
@Root(name = "RootNode")
class RootNode {
// TODO: What annotations to put here?
private List<FooEntity> fooEntities;
// TODO: What annotations to put here?
private List<BarEntity> barEntities;
public List<FooEntity> getFooEntities() { return fooEntities; }
public List<BarEntity> getBarEntities() { return barEntities; }
}
class FooEntity {
@Element(name = "URL")
private String url;
}
class BarEntity {
@Element(name = "Price")
private int price;
}
现在真正的问题...
// TODO: What annotations to put here?
private List<BarEntity> barEntities;
我的回答:没有! 或者至少,没关系!
像属性type
,这里只是字符串,而不能作出任何决定。 但还有另一种不错的方式:
- 实现了转换
RootNode
这确实决定 - 使用
Serializer
做反序列化每个实体的实际工作。
我做了一些修改你的类,但没有壮观已经改变。 的toString()
-方法仅用于测试-实现,因为你需要它。
类FooEntity
@Root(name = "Entity")
public class FooEntity
{
@Attribute(name = "type")
private String type;
@Element(name = "Price")
private int price;
/*
* NOTE: A default ctor is required - visibile doesn't matter
*/
@Override
public String toString()
{
return "FooEntity{" + "price=" + price + '}';
}
}
类BarEntity
@Root(name = "Entity")
public class BarEntity
{
@Attribute(name = "type")
private String type;
@Element(name = "URL")
private String url;
/*
* NOTE: A default ctor is required - visibile doesn't matter
*/
@Override
public String toString()
{
return "BarEntity{" + "url=" + url + '}';
}
}
类RootNode
@Root(name = "RootNode")
@Convert(RootNodeConverter.class) // <--- Important!
class RootNode
{
private List<FooEntity> fooEntities;
private List<BarEntity> barEntities;
public RootNode()
{
// This has to be done somewhere ...
this.fooEntities = new ArrayList<>();
this.barEntities = new ArrayList<>();
}
public List<FooEntity> getFooEntities()
{
return fooEntities;
}
public List<BarEntity> getBarEntities()
{
return barEntities;
}
@Override
public String toString()
{
return "RootNode{" + "fooEntities=" + fooEntities + ", barEntities=" + barEntities + '}';
}
}
最后的Converter
-实施:
类RootNodeConverter
public class RootNodeConverter implements Converter<RootNode>
{
@Override
public RootNode read(InputNode node) throws Exception
{
RootNode root = new RootNode();
final InputNode entities = node.getNext("Entities");
InputNode child;
while( ( child = entities.getNext() ) != null )
{
if( child.getName().equals("Entity") == false )
{
continue; // Not an Entity
}
final Serializer ser = new Persister();
switch(child.getAttribute("type").getValue())
{
case "foo":
root.getFooEntities().add(ser.read(FooEntity.class, child));
break;
case "bar":
root.getBarEntities().add(ser.read(BarEntity.class, child));
break;
default:
// Not a Foo nor a Bar - what now!?
break;
}
}
return root;
}
@Override
public void write(OutputNode node, RootNode value) throws Exception
{
throw new UnsupportedOperationException("Not implemented yet!");
}
}
有一些事情进行优化,例如。 添加root.addBar(ser.read(BarEntity.class, child))
或ErrorHandling中一般。
顺便说一句。 而不是两个列表,您可以维护一个单一的一个(如果相关)。 只是要为实体的超类。 您可以在移动type
-attribute到那里了。
用法
下面是一个例子如何使用:
final String input = "<RootNode>\n"
+ " <Entities>\n"
+ " <Entity type=\"foo\">\n"
+ " <Price>1</Price>\n"
+ " </Entity>\n"
+ "\n"
+ " <Entity type=\"bar\">\n"
+ " <URL>www.google.co.uk</URL>\n"
+ " </Entity>\n"
+ "\n"
+ " <Entity type=\"foo\">\n"
+ " <Price>77</Price>\n"
+ " </Entity>\n"
+ " </Entities>\n"
+ "</RootNode>";
final Serializer ser = new Persister(new AnnotationStrategy()); // <-- Note the strategy!
RootNode root = ser.read(RootNode.class, input);
System.out.println(root);
真的没什么壮观这里太...
输出:
RootNode{fooEntities=[FooEntity{price=1}, FooEntity{price=77}], barEntities=[BarEntity{url=www.google.co.uk}]}