我有一个包含许多Entity元素的XML文档,每个元素都有一个type="foo"或属性type="bar"。看到这个例子:
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>
我需要一种方法告诉Simple将Entity元素反序列type="foo"化为a List<FooEntity>和将元素反序列type="bar"化为a List<BarEntity>。
List<FooEntity>
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这里这样的属性只是字符串,不能做出任何决定。但是还有另一种好方法:
type
RootNode
Serializer
我对您的课程进行了一些修改,但没有任何改变。的toString()-方法仅用于测试-实现,因为你需要它。
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 + '}'; } }
@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实现:
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))通常添加或错误处理。
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}]}