我正在尝试使用simpleXML将XML文件反序列化为Java对象。一切都很好,直到我不得不使用ElementMap。 这是我的XML文件的一部分:
<piece composer="Me" date="Yesterday" title="Important work">
<editions>
<edition name="My Name" date="2015" description="A single page">
<pages>
<page fileName="page01.jpg" />
</pages>
</edition>
<edition name="My Name again" date="2015" description="Another single page">
<pages>
<page fileName="page01.jpg" />
</pages>
</edition>
</editions>
<layers>
<layer name="Annotations" color="#FF0000" description="Empty" id="anno" />
<layer name="Information" color="#00FF00" description="Empty" id="info" />
</layers>
</piece>
相应的Java类如下所示:
@Root
public class Piece {
@Attribute
private String composer;
@Attribute
private String title;
@Attribute
private String date;
@ElementList
private List<Edition> editions;
@ElementMap(key = "id", attribute = true) // Relevant
private Map<String, Layer> layers; // Lines
public static Piece loadFromAsset(Context context, String fileName) throws Exception {
Serializer serial = new Persister();
return serial.read(Piece.class, context.getResources().getAssets().open(fileName));
}
}
最后是Layer Class:
public class Layer {
@Attribute
private String id;
@Attribute
private String name;
@Attribute
private String description;
@Attribute
private String color;
}
加载XML文件后,Map包含两个键,但它们都指向null
而不是实际的图层对象。
答案 0 :(得分:0)
我不是SimpleFrawmerow用户,所以我不保证它会起作用,但你应该指定更多的ElementMap映射的地址:
@ElementMap(key = "id", attribute = true, keyType=String.class
,valueType=Layer.class)
如果没有帮助,您必须自己处理列表以进行地图转换。问题是你的xml实际上是一个Layer元素列表而不是map(没有键/值元素对)。
您可以添加Piece类额外字段来存储该列表,并使用它构建地图字段:
class Piece {
...
@ElementList //only for solution B, for a do not use this annotation
List<Layer> layers;
@Transient //importatnt as it does not go into xml directly
private Map<String, Layer> layersMap;
}
现在有两种方法:
A)为图层列表使用getter和setter,并在方法内部根据需要构建列表映射内容:
@ElementList
public void setLayers(Collection<Layer> layers) {
layersMap = new HashMap<>();
for (Layer l : layers) layersMap.put(l.getId(),l);
}
@ElementList
public Collection<Layer> getLayers() {
return layersMap.values();
}
B)使用序列化生命周期机制(Persist和Commit annotations)。在序列化之前调用的一个方法中,使用另一个中的映射创建列表内容,使用列表值填充映射。我个人更喜欢它,因为你可以隐藏'layers'元素。
class Piece {
....
@Commit
public void prepareMap() {
layersMap = new HashMap<>();
for (Layer l : layers) layersMap.put(l.getId(),l);
}
@Persist
public void prepareList() {
layers = new ArrayList<>();
layers.addAll(layersMap.values());
}
}
最后,您可以使用转换器完全控制该过程,但我相信上述内容更容易,更简洁。