如何解决根据属性将XML元素反序列化为不同类型
现在真正的问题…
// Todo: What annotations to put here?
private List<BarEntity> barEntities;
没有!或至少,没关系!
像type
这里这样的属性只是字符串,不能做出任何决定。但是还有另一种好方法:
- 实施要
RootNode
为其做出决定的转换器 - 使用a
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))
通常添加或错误处理。
顺便说一句。而不是 2个 列表,您可以维护一个 单一的 一个(如果相关)。只需为实体创建超类。您也可以将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}]}
解决方法
我有一个包含许多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
元素反序列type="foo"
化为a
List<FooEntity>
和将元素反序列type="bar"
化为a 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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。