如何在将List添加到List后让JAXB调用setter?

时间:2014-09-10 13:48:37

标签: java xml jaxb

我在XML文件中有一些数据,我想用JAXB解组到MyHashMap中。 MyObject有一个String名称,这是我的HashMap中的关键字。

为了防止将键/名称信息两次写入我的XML文件(一次作为MyObject的名称,一次作为MyHashMap的键),所以我为一个ArrayList添加了setter和getter,它将数据添加/读入/离开MyHashMap。

@XmlRootElement
public class MyHashMap extends HashMap<String, MyObject> implements Serializable {

    public MyHashMap() {
        super();
    }

    @XmlElement(name = "MyObject")
    public void setMyObjectsArrayList(ArrayList<MyObject> MyObjectList) {
        for (MyObject myObject : MyObjectList) {
            this.put(myObject.getName(), myObject);
        }
    }

    public ArrayList<MyObject> getMyObjectsArrayList() {
        if (this.isEmpty()) { // Added this to get my setter called
            return null;
        }
        ArrayList<MyObject> MyObjectList = new ArrayList<MyObject>();
        MyObjectList.addAll(this.values());
        return MyObjectList;
    }
}

它在Java 7中运行良好(根据this的问题因为一个错误),但在Java 8中没有。 在Java 8中,JAXB获取ListObject并添加Elemts而不是使用setter。

所以我添加了一个&#34;返回null&#34;如果列表为空。 显然JAXB然后设置一个空列表,然后添加元素,这显然不适用于我的代码。 是否有可能告诉JAXB将Elements添加到列表中并仅调用setter?

1 个答案:

答案 0 :(得分:1)

您可以使用Map,因为JAXB将编组并解组它。 (参见https://jaxb.java.net/tutorial/section_6_2_1-A-Survey-Of-JAXB-Annotations.html)为避免重复名称,请在MyObject中使用@XmlTransient进行注释。

另一种方法是使用适配器;您必须将Map包装到父元素中。见https://jaxb.java.net/tutorial/section_6_2_9-Type-Adapters-XmlJavaTypeAdapter.html

另一种可能性是使用更简单的方法,根元素类的实现略有不同。它可以让你像地图一样使用MyHashMap并避免所有肮脏的伎俩,尽管访问者调用起来有点不方便。当然,您也可以实现Map并清理,但需要编写更多代码。

@XmlRootElement
public class MyHashMap {
    private boolean dirty = false;
    private Map<String,MyObject> str2obj;
    private List<MyObject> myObjects = new ArrayList<>();

    @XmlElement(name = "MyObject")
    List<MyObject> getMyObjects(){
        dirty = true;
        return myObjects();
    }

    // variant 1: expose str2obj
    @XmlTransient
    public Map<String,MyObject> getStr2Obj(){
        if( dirty ) rebuild();
        return str2obj;
    }

    private void rebuild(){
        str2obj.clear();
        for( MyObject myObject: myObjects ){
            str2obj.put(mmyObject.getName(), myObject );
        }
        dirty = false;
    }

    // variant 2: delegate put, get, and other methods
    // use the same approach
}