Вопрос по java, xml, jaxb – JAXB не разбирает список интерфейсов

7

Кажется, JAXB не может прочитать то, что пишет. Рассмотрим следующий код:

interface IFoo {
    void jump();
}

@XmlRootElement
class Bar implements IFoo {
    @XmlElement
    public String y;

    public Bar() {
        y = "";
    }

    public Bar(String y) {
        this.y = y;
    }

    @Override
    public void jump() {
        System.out.println(y);
    }
}

@XmlRootElement
class Baz implements IFoo {
    @XmlElement
    public int x;

    public Baz() {
        x = 0;
    }

    public Baz(int x) {
        this.x = x;
    }

    @Override
    public void jump() {
        System.out.println(x);
    }
}

@XmlRootElement
public class Holder {
    private List<IFoo> things;

    public Holder() {
        things = new ArrayList<>();
    }

    @XmlElementWrapper
    @XmlAnyElement
    public List<IFoo> getThings() {
        return things;
    }

    public void addThing(IFoo thing) {
        things.add(thing);
    }
}

// ...

try {
    JAXBContext context = JAXBContext.newInstance(Holder.class, Bar.class, Baz.class);

    Holder holder = new Holder();
    holder.addThing(new Bar("1"));
    holder.addThing(new Baz(2));
    holder.addThing(new Baz(3));

    for (IFoo thing : holder.getThings()) {
        thing.jump();
    }

    StringWriter s = new StringWriter();
    context.createMarshaller().marshal(holder, s);

    String data = s.toString();

    System.out.println(data);

    StringReader t = new StringReader(data);
    Holder holder2 = (Holder)context.createUnmarshaller().unmarshal(t);

    for (IFoo thing : holder2.getThings()) {
        thing.jump();
    }
}
catch (Exception e) {
    System.err.println(e.getMessage());
}

Конечно, это упрощенный пример. Дело в том, что мне нужно хранить два совершенно разных реализованных класса, Bar и Baz, в одной коллекции. Ну, я заметил, что у них довольно похожий публичный интерфейс, поэтому я создал интерфейс IFoo и сделал их два для его реализации. Теперь я хочу иметь инструменты для сохранения и загрузки этой коллекции в / из XML. К сожалению, этот код не работает: коллекция сохранена, но затем ее невозможно загрузить! Предполагаемый результат

1
2
3
some xml
1
2
3

Но, к сожалению, фактический результат

1
2
3
some xml
com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to testapplication1.IFoo

Видимо, мне нужно использовать аннотации по-другому? Или отказаться от JAXB и искать что-то еще? Ну, я могу написать "XMLNode toXML ()" метод для всех классов, которые я бы хотел (де) маршал, но ...

Проверьте документацию для использования @XmlSeeAlso Adam Arold
Возможный дубликатstackoverflow.com/questions/4144296/…, который также спрашивает о списке типов интерфейса и имеет другой, рабочий подход в принятом ответе. Andy Thomas

Ваш Ответ

1   ответ
9

@XmlAnyElement(lax=true),lax флаг указывает реализации JAXB (JSR-222) сопоставлять элементы с объектами домена на основе их@XmlRootElement а также@XmlElementDecl аннотаций. Без этого содержимое рассматривается как узлы DOM.

@XmlRootElement
public class Holder {
    private List<IFoo> things;

    public Holder() {
        things = new ArrayList<>();
    }

    @XmlElementWrapper
    @XmlAnyElement(lax=true)
    public List<IFoo> getThings() {
        return things;
    }

    public void addThing(IFoo thing) {
        things.add(thing);
    }
}

For More Information

http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html
Оно работает. Спасибо! Но, черт возьми, все эти вещи JAXB похожи на черную магию, я пока не нашел для них понятного руководства. Joker_vD
Каковы преимущества и недостатки этого подхода по сравнению с подходом, который вы предоставили в своем ответе на предыдущий вопрос, связанный ниже? (Например, более ранний ответ, кажется, предполагает, что набор реализаций известен классу, содержащему список.)stackoverflow.com/a/4145801/202009
@Joker_vD - оформить заказ на мой Java XML & amp; JSON Binding блог (blog.bdoughan.com) и руководство пользователя EclipseLink JAXB (MOXy) (wiki.eclipse.org/EclipseLink/UserGuide/MOXy)

Похожие вопросы