簡體   English   中英

反序列化最終列表屬性

[英]Deserialize a final list attribute

假設我們有一個類測試,如:

public class Test {
    private final String name;
    private final List<String> list = new ArrayList<>();

    public Test(String name) {
        this.name = name;
    }

    void add(String s) {
        list.add(s);
    }

    void print() {
        System.out.println("name: " + name);
        for (String s : list) {
            System.out.println(" - " + s);
        }
    }
}

沒有XSteam的不變量

this.list != null

每次都持有。

但是,如果我們看看第四次測試

public static void main(String[] args) {
    final XStream xstream = new XStream();
    xstream.alias("test", Test.class);

    // Serialize
    final Test test1 = new Test("XYZ");
    test1.add("One");
    test1.add("Two");

    //@formatter:off
    /* name: XYZ
     *  - One
     *  - Two
     */
    //@formatter:on
    test1.print();

    //@formatter:off
    /* <test>
     *   <name>XYZ</name>
     *   <list>
     *     <string>One</string>
     *     <string>Two</string>
     *   </list>
     * </test>
     */
    //@formatter:on
    System.out.println(xstream.toXML(test1));

    // Deserialize with one list entry
    final String xmlTest2 = "<test><name>XYZ</name><list><string>One</string></list></test>";
    final Test test2 = (Test) xstream.fromXML(xmlTest2);
    //@formatter:off
    /* <test>
     *   <name>XYZ</name>
     *   <list>
     *     <string>One</string>
     *   </list>
     * </test>
     */
    //@formatter:on
    test2.print();

    // Deserialize with empty list
    final String xmlTest3 = "<test><name>XYZ</name><list /></test>";
    final Test test3 = (Test) xstream.fromXML(xmlTest3);
    //@formatter:off
    /* name: XYZ
     */
    //@formatter:on
    test3.print();

    // Deserialize without list-tag
    final String xmlTest4 = "<test><name>XYZ</name></test>";
    final Test test4 = (Test) xstream.fromXML(xmlTest4);
    //@formatter:off
    /* name: XYZ
     * Exception in thead ... NullPointerException
     */
    //@formatter:on
    test4.print();
}

我們看到一個NullPointerException,因為list沒有初始化。

我想讓XML中的list -element與test4類似。 我能做什么? 因為我的數據模型中有很多類與Test類似,所以我不想為每個類編寫一個Converter 但是假設我會寫一個Converter ,我該如何設置最終的屬性name

請使用XStream Annotations和自定義Converter找到以下解決方案。

自定義轉換器是以下類:

 public class ListableConverter implements Converter {

    public void marshal(Object source, HierarchicalStreamWriter writer,
            MarshallingContext context) {
        Listable listable = (Listable) source;
        writer.setValue(String.valueOf(... your marshalling logic here ...));
    }

    public Object unmarshal(HierarchicalStreamReader reader,
            UnmarshallingContext context) {
        List<String> list = new ArrayList<String>();
        // your unmarshalling logic here
        return list;
    }

    public boolean canConvert(Class type) {
        return type instanceof Listable;
    }
}

這是帶有Annotations的修改過的Test類:

public class Test implements Listable{
    private final String name;

    @XStreamConverter(ListableConverter.class)
    private final List<String> list = new ArrayList<>();

    public List<String> getList() {
        return list;
    }

    public Test(String name) {
        this.name = name;
    }

    void add(String s) {
        list.add(s);
    }

    void print() {
        System.out.println("name: " + name);
        for (String s : list) {
            System.out.println(" - " + s);
        }
    }
}

最后,用於使轉換器的接口適用於實現接口的模型中的任何類:

public interface Listable<String> {

    public List<String> getList();

}

因此,例如,模型中的另一個類可能如下所示:

    public class Foo implements Listable{

        @XStreamConverter(ListableConverter.class)
        private final List<String> anotherList = new ArrayList<>();

        ... omissis ...

        public List<String> getList() {
          return anotherList;
        }

   }

XStream在增強模式下使用munged構造函數(http://stackoverflow.com/questions/1426106/why-are-constructors-returned-by-reflectionfactor-newconstructorforserialization)(默認)。 您可以通過在純模式下初始化XStream來更改此行為:

XStream xstream = new XStream(new PureJavaReflectionProvider());

另一種選擇是使用getter訪問變量並實現延遲初始化。

public class Test {
private final String name;
private List<String> list;

public Test(String name) {
    this.name = name;
}

void add(String s) {
    list.add(s);
}

List<String> getList() {
  if (list == null) {
    list = new ArrayList<>();
  }
  return list;
}

void print() {
    System.out.println("name: " + name);
    for (String s : getList()) {
        System.out.println(" - " + s);
    }
}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM