2012-06-20 16 views
7

Parece que JAXB no puede leer lo que escribe. Considere el siguiente código:JAXB no anula la lista de interfaces

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()); 
} 

Es un ejemplo simplificado, por supuesto. El punto es que tengo que almacenar dos clases implementadas de forma muy diferente, Bar y Baz, en una sola colección. Bueno, observé que tienen una interfaz pública bastante similar, así que creé una interfaz IFoo y les hice dos para implementarla. Ahora, quiero tener herramientas para guardar y cargar esta colección desde/hacia XML. Lamentablemente, este código no funciona: la colección se guarda, pero luego no se puede cargar. El resultado previsto es

1 
2 
3 
some xml 
1 
2 
3 

Pero, por desgracia, la salida real es

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

Al parecer, necesito usar las anotaciones de una manera diferente? ¿O renunciar a JAXB y buscar algo más? Yo, bueno, puedo escribir el método "XMLNode toXML()" para todas las clases que quiero (de) Marshal, pero ...

+0

Consulte la documentación para el uso de @XmlSeeAlso –

+0

duplicado Posible de http://stackoverflow.com/questions/4144296/marshalling -a-list-of-objects-with-jaxb, que también pregunta acerca de una lista de un tipo de interfaz, y tiene un enfoque de trabajo diferente en la respuesta aceptada. –

Respuesta

8

Pruebe el siguiente @XmlAnyElement(lax=true). El indicador lax le dice a la implementación de JAXB (JSR-222) que haga coincidir los elementos con los objetos de dominio según sus anotaciones @XmlRootElement y @XmlElementDecl. Sin él, los contenidos se tratan como nodos 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); 
    } 
} 

Para más información

+6

Funciona. ¡Gracias! Pero Dios, todo esto de JAXB es como magia negra, todavía tengo que encontrar una guía indescifrable. –

+1

@Joker_vD - Verifique mi blog Java XML & JSON Binding (http://blog.bdoughan.com/) y la Guía del usuario de EclipseLink JAXB (MOXy) (http://wiki.eclipse.org/EclipseLink/UserGuide/MOXy) –

+0

¿Cuáles son las ventajas y desventajas de este enfoque en comparación con el enfoque que proporcionó en su respuesta a la pregunta anterior vinculada a continuación? (Por ejemplo, la respuesta anterior parece suponer que el conjunto de implementaciones es conocido por la clase que contiene la lista). Http://stackoverflow.com/a/4145801/202009 –

Cuestiones relacionadas