2010-12-16 13 views
6

Bitte beachten Sie das folgende Beispiel wird eine Klasse erweitert:JAXB: Problem eine Klasse B Deserialisieren, die mit A

Es gibt einen KlasseA und einen ClassB die es erstreckt. Mein Problem ist jetzt, dass ich eine ClassB von einer xml-Datei entfernen muss. Bitte beachten Sie, dass ClassA nicht geändert werden kann, da es nicht unter meiner Kontrolle steht.

Mehrere Probleme sind in diesem Beispiel festgestellt:

Das Hauptproblem ist, dass KlasseA keinen Standard hat kein argument Konstruktor, die von JAXB ohne Adapter erforderlich ist. Daher implementierte ich MyAdapter, die ClassB auf die einfache Klasse ValB abbildet, die von JAXB ohne Probleme verarbeitet werden kann.

Das Hauptproblem ist, wie man JAXB diesen Adapter benutzen lässt? Weder die Definition des @XmlJavaTypeAdapter auf Klassenebene noch die Registrierung des Adapters beim Unmarshaller machen es.

Weiß jemand, wie JAXB MyAdapter, so dass die Unmarshaller gibt ein Objekt, das ist eine Instanz KlasseA verwenden zu machen?

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: Nehmen Sie den Code nicht zu ernst - es ist nur ein Beispiel für das Problem. Ich weiß, dass die Definition von ClassA und ClassB nicht wirklich nützlich sind.

+0

Wir haben dieses Problem in t angesprochen er kommenden EclipseLink JAXB (MOXy) Release. In dieser Version sind keine Codeänderungen in Ihrem Beispiel erforderlich: http://stackoverflow.com/questions/4459737/jaxb-problem-deserializing-a-class-b-that-extends-a-class-a/4459779#4459779 –

Antwort

2

UPDATE

Wir haben dieses Problem in den kommenden EclipseLink JAXB (MOXy) 2.2.0 Release angesprochen haben (siehe bug #332742). In dieser Version werden abstrakte Klassen nicht auf einen Konstruktor ohne Argumente überprüft.

Pre-Release-Versionen mit diesem Update finden Sie hier beginnend 18. Dezember erhalten:

Umgehung

Dies ist, was die @XmlTransient Anmerkung für ist. Wenn möglich, gehen Sie wie folgt vor:

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

Wenn es nicht möglich ist KlasseA direkt mit Anmerkungen versehen, könnten Sie eine EclipseLink JAXB (MOXy) Erweiterung nutzen, dies zu tun. Mit MOXy können Sie JAXB-Metadaten als XML-Datei angeben.Dies ist nützlich, wenn man nicht eine Modellklasse ändern:

Im Folgenden sind einige Artikel erklärt @XmlAdapter:

+0

Beide Artikel sind unterschiedlich, da das unveränderliche Objekt ein Feld einer Kapselungsklasse ist - was in meinem Beispiel nicht der Fall ist. – Robert

+0

Danke für die Info, auch wenn ich die JAXB-Version der JRE nutzen wollte. Der interessanteste Teil Ihrer Antwort ist, dass MOXy den gleichen Fehler hat/hatte. Kann das ein Fall sein, der außerhalb der JAXB-Spezifikation liegt oder basiert MOXy auf denselben Quellen wie die Implementierung von SUN/Oracle? – Robert

+0

Die Codebasen sind vollständig unabhängig. Beide Gruppen haben sich entschieden, den No-Arg-Check für alle Klassen durchzuführen. Zumindest jetzt in EclipseLink JAXB (MOXy) haben wir es behoben. Vielen Dank für die Identifizierung des Problems. –