2010-12-16 15 views
6

Por favor, considere el siguiente ejemplo:JAXB: Problema deserializar una clase B que se extiende una clase A

Hay una claseA y una ClassB que se extiende la misma. Mi problema ahora es que tengo que deshacerme de un ClassB de un archivo xml. Tenga en cuenta que Clase A no se puede cambiar, ya que no está bajo mi control.

Varios problemas se observan en este ejemplo:

El principal problema es que claseA no tiene un defecto sin argumentos constructor que es requerido por JAXB sin adaptador. Por lo tanto, implementé MyAdapter que asigna ClassB a la clase simple ValB que puede ser procesada por JAXB sin ningún problema.

El principal problema es cómo hacer que JAXB use este adaptador? Ni la definición del @XmlJavaTypeAdapter en el nivel de clase ni el registro del Adaptador en el unmarshaller lo hace.

¿Alguien sabe cómo hacer uso de JAXB MyAdapter para que el unmarshaller devuelve un objeto que es una instancia de claseA?

public class JaxbTest { 

    public static abstract class ClassA { 
     public ClassA(String id) { 
     } 
    } 

    @XmlRootElement 
    @XmlJavaTypeAdapter(MyAdapter.class) // does not have an effect 
    public static class ClassB extends ClassA { 

     public String text; 

     public ClassB() { 
      super(""); 
     } 
    } 

    public static class ValB { 
     public String text; 
    } 

    public static class MyAdapter extends XmlAdapter<ValB, ClassB> { 

     @Override 
     public ClassB unmarshal(ValB v) throws Exception { 
      ClassB b = new ClassB(); 
      b.text = v.text; 
      return b; 
     } 

     @Override 
     public ValB marshal(ClassB v) throws Exception { 
      ValB b = new ValB(); 
      b.text = v.text; 
      return b; 
     } 

    } 

    public static void main(String[] args) { 
     try { 
      JAXBContext context = JAXBContext.newInstance(ClassB.class); 
      Unmarshaller unmarshaller = context.createUnmarshaller(); 
      unmarshaller.setAdapter(new MyAdapter()); // does not have an effect 
      ClassA a = (ClassA) unmarshaller.unmarshal(new File("test.xml")); 
      // do somthing with a 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

BTW: No tome el código demasiado en serio, es solo un ejemplo que demuestra el problema. Sé que la definición de Clase A y Clase B no es realmente útil.

+0

Hemos abordado este problema en t la próxima versión de EclipseLink JAXB (MOXy). En esta versión no se requieren cambios de código en su ejemplo: http://stackoverflow.com/questions/4459737/jaxb-problem-deserializing-a-class-b-that-extends-a-class-a/4459779#4459779 –

Respuesta

2

ACTUALIZACIÓN

Hemos abordado esta cuestión en la próxima versión 2.2.0 EclipseLink JAXB (MOXy) (ver bug #332742). En este lanzamiento, las clases abstractas no se verificarán para un constructor no arg.

Las versiones preliminares con esta revisión se pueden obtener aquí a partir décima octava diciembre:

Solución

Esto es lo que la anotación es para @XmlTransient. Si es posible hacer lo siguiente:

@XmlTransient 
public static abstract class ClassA { 
    public ClassA(String id) { 
    } 
} 

Si no es posible realizar anotaciones directamente claseA, se podría aprovechar una extensión EclipseLink JAXB (MOXy) para hacer esto. MOXy le permite especificar los metadatos de JAXB como un archivo XML.Esto es útil cuando no se puede modificar una clase de modelo:

A continuación se presentan algunos artículos que explican @XmlAdapter:

+0

Ambos artículos son diferentes porque el objeto inmutable es un campo de una clase encapsulante, que no es el caso en mi ejemplo. – Robert

+0

Gracias por la información, incluso si tenía la intención de utilizar la versión JAXB que viene con el JRE. La parte más interesante de su respuesta es que MOXy tiene/tuvo el mismo error. ¿Puede ser que este es un caso que se encuentra fuera de la especificación JAXB o MOXy está basado en las mismas fuentes que la implementación de SUN/Oracle? – Robert

+0

Las bases de los códigos son completamente independientes. Ambos grupos decidieron hacer el control no arg en todas las clases. Al menos ahora en EclipseLink JAXB (MOXy) lo hemos solucionado. Gracias por identificar el problema. –

Cuestiones relacionadas