我有一个包含许多Entity
个元素的XML文档,每个元素的属性都是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>
我需要一种方法告诉Simple将带有Entity
的{{1}}元素反序列化为type="foo"
,将带有List<FooEntity>
的元素反序列化为{{1} }}
我该怎么做?
如果您想要使用它,我现在拥有的代码如下:
type="bar"
答案 0 :(得分:1)
现在真正的问题......
// 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))
或错误处理。
顺便说一下。而不是两个列表,您可以维护单个一个(如果相关)。只需为实体创建一个超类。您也可以将type
- 属性移动到那里。
以下是如何使用的示例:
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}]}