Использование XStream для создания списка различных объектов

Я создаю программу на Java, которая содержит древовидную структуру объектов. Все задействованные классы реализуют один и тот же интерфейс, и каждый класс содержит список дочерних элементов:

public class MyClass1 implements MyInterface {    
    List<MyInterface> children;
}

public class MyClass2 implements MyInterface {    
    List<MyInterface> children;
}

public class MyClass3 implements MyInterface {    
    List<MyInterface> children;
}

....

Теперь в XML-файле определены три структуры:

<myclass1>
    <myclass2></myclass2>
    <myclass1>
        <myclass3></myclass3>
    </myclass1>
</myclass1>

Древовидная структура может быть любого типа, определенного пользователем. Конечно, каждый класс содержит специфичные для класса переменные, которые я пока не опустил.

Сейчас я пытаюсь использовать XStream для десериализации XML-файла в Java-объекты, желательно с использованием аннотаций, но я не знаю, как это сделать. Я не хочу в конечном итоге составлять список для каждого возможного класса, например. в MyClass1:

@XStreamImplicit(itemFieldName="myclass2")
List<MyClass2> children2;
@XStreamImplicit(itemFieldName="myclass3")
List<MyClass3> children3;
@XStreamImplicit(itemFieldName="myclass4")
List<MyClass4> children4;

Есть предложения, как решить этот случай с помощью XStream? Или стоит использовать другие технологии?


person Remco    schedule 23.08.2012    source источник


Ответы (1)


source.xml (содержащий XML, который мы хотим загрузить):

<myclass1>
    <myclass2></myclass2>
    <myclass1>
        <myclass3></myclass3>
    </myclass1>
</myclass1>

Интерфейс:

import java.util.List;

public interface Myinterface {
    List<? extends Myinterface> getChildren();
}    

Класс абстрактного компонента (объявление потомков с @XStreamImplicit):

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamImplicit;

public class MyAbstract implements Myinterface {
    @XStreamImplicit
    private List<? extends Myinterface> children = new ArrayList<Myinterface>();


    public List<? extends Myinterface> getChildren() {
        return children;
    }
}

Классы компонентов (расширение MyAbstract, использование @XStreamAlias для использования нужной XML-строки):

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias(value="myclass1")
public class Myclass1 extends MyAbstract {

}

@XStreamAlias(value="myclass2")
public class Myclass2 extends MyAbstract {

}

@XStreamAlias(value="myclass3")
public class Myclass3 extends MyAbstract {

}

Основной класс (чтение исходного XML-файла. Не забудьте processAnnotations загрузить конфигурацию из аннотированных классов):

import com.thoughtworks.xstream.XStream;

public class XStreamTest {
    public static void main(String[] args) {
        XStream xStream = new XStream();
        xStream.processAnnotations(Myclass1.class);
        xStream.processAnnotations(Myclass2.class);
        xStream.processAnnotations(Myclass3.class);

        Object fromXML = xStream.fromXML(XStreamTest.class.getResourceAsStream("source.xml"));
        System.out.println(fromXML);
    }
}
person Toilal    schedule 23.08.2012
comment
Спасибо, это действительно полезно! - person Remco; 23.08.2012
comment
@Toilal, как получить значение элемента, который сам является классом. У меня есть тот, который похож на предыдущий, за исключением того, что «‹myclass1› ‹myclass2› ‹myclass1› abc ‹myclass1› ‹myclass2› ‹myclass1›». Я не могу получить значение myclass1 = abc - person chetank; 30.04.2015