2011-02-15 19 views
8

Mam klasę Animal i rozszerzenie Animal o nazwie AnimalExtension.JAXB @XmlElements, różne typy, ale takie same nazwy?

public class Animal 

public class AnimalExtension extends Animal 

Jedyna różnica między tymi dwiema klasami polega na tym, że AnimalExtension ma inną zmienną instancji o nazwie animalId. Zwierzę nie ma tej instancji zmiennej.

Mam również swój własny typ danych, który chcę zabezpieczyć i przypisać do formatu XML. Ten typ danych nosi nazwę AnimalList. wewnątrz AnimalList znajduje się lista zwierząt jako zmienna instancji.

@XmlType(name = "AnimalList") 
public class AnimalList{ 
    private List<Animal> animalList; 
    .... 

animalList może zawierać zarówno zwierzęce, jak i zwierzęce rozszerzenie. Jednak na XML nie chcę, aby element był nazywany AnimalExtension; Chcę, żeby wszyscy mieli imię zwierzęcia. Chcę tylko, aby dodatkowy atrybut pojawił się, gdy JAXB wie, że Animal jest faktycznie instancją AnimalExtension. Więc jeśli mam listę, która wygląda jak

List<Animal> animalList = new LinkedList<Animal>(); 
AnimalExtension animalExtension = new AnimalExtension(); 
animalExtension.setAnimalId(1); 
amimalExtension.setName("Don"); 

Animal animal = new Animal(); 
animal.setName("Mike"); 
animalList.add(animalExtension); 
animalList.add(animal); 

chcę XML wyglądać

<AnimalList> 
    <Animal name="Don" id="1" /> 
    <Animal name="Mike" /> 
</AnimalList> 

To jest to, co starałem się zrobić

@XmlElements(
    { 
      @XmlElement(name = "Animal", type = Animal.class), 
      @XmlElement(name = "Animal", type = AnimalExtension.class) 
     } 
    ) 
    public List<Animal> getEntries() { 
     return animalList; 
    } 

Kod kompiluje ale kiedy próbuję uruchomić mój serwer. Daje mi to dziwny błąd, który jest tak niezwiązany z tym, co się dzieje (BeanCreationException). Próbowałem, aby nazwa XmlElement była inna dla każdego typu i działa, ale wyzwaniem jest tutaj, aby nazwa była taka sama.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'encryptionPayloadContentProvider' 
+5

Biorąc pod uwagę jak jest JAXB XML powinien określić, która klasa używać do tworzenia obiektów Javy? Czy jest to atrybut "id"? Co jeśli istnieje inna klasa o nazwie "AnimalEnhacement" z atrybutem id? –

+0

dobry punkt lol. Nie myślałem o tym. – denniss

Odpowiedz

9

Aby odwzorować ten przypadek użycia można wykorzystać następujące XmlAdapters:

AnimalAdapter

Od AnimalExtension jest super zestaw Animal będziemy używać go do produkcji/konsumpcji XML. Następnie wykorzystamy wartość właściwości animalId w celu ustalenia, czy instancja Animal lub AnimalExtension zostanie zwrócona do AnimalList.

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class AnimalAdapter extends XmlAdapter<AnimalExtension, Animal> { 

    @Override 
    public Animal unmarshal(AnimalExtension animalExtension) throws Exception { 
     if(0 != animalExtension.getAnimalId()) { 
      return animalExtension; 
     } 
     Animal animal = new Animal(); 
     animal.setName(animalExtension.getName()); 
     return animal; 
    } 

    @Override 
    public AnimalExtension marshal(Animal animal) throws Exception { 
     if(animal.getClass() == AnimalExtension.class) { 
      return (AnimalExtension) animal; 
     } 
     AnimalExtension animalExtension = new AnimalExtension(); 
     animalExtension.setName(animal.getName()); 
     return animalExtension; 
    } 

} 

IdAdapter

Będziemy potrzebować drugi XmlAdapter stłumić animalId jeżeli jego wartość jest równa 0:

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class IdAdapter extends XmlAdapter<String, Integer> { 

    @Override 
    public Integer unmarshal(String string) throws Exception { 
     return Integer.valueOf(string); 
    } 

    @Override 
    public String marshal(Integer integer) throws Exception { 
     if(integer == 0) { 
      return null; 
     } 
     return String.valueOf(integer); 
    } 

} 

klasach model zostanie odnotowany w następujący sposób:

AnimalList

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

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement(name="AnimalList") 
public class AnimalList { 

    private List<Animal> animalList = new ArrayList<Animal>(); 

    @XmlElement(name="Animal") 
    @XmlJavaTypeAdapter(AnimalAdapter.class) 
    public List<Animal> getEntries() { 
     return animalList; 
    } 

} 

Animal

import javax.xml.bind.annotation.XmlAttribute; 

public class Animal { 

    private String name; 

    @XmlAttribute 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

AnimalExtension

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

public class AnimalExtension extends Animal { 

    private int animalId; 

    @XmlAttribute(name="id") 
    @XmlJavaTypeAdapter(IdAdapter.class) 
    public int getAnimalId() { 
     return animalId; 
    } 

    public void setAnimalId(int animalId) { 
     this.animalId = animalId; 
    } 

} 

Code Demo

Poniższy kod demo może być stosowane do wykazania tego rozwiązania:

import java.io.File; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(AnimalList.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("input.xml"); 
     AnimalList animalList = (AnimalList) unmarshaller.unmarshal(xml); 

     for(Animal animal : animalList.getEntries()) { 
      System.out.println(animal.getClass()); 
     } 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(animalList, System.out); 
    } 

} 

Poniższy wyjście będzie produkowany:

class AnimalExtension 
class Animal 
<?xml version="1.0" encoding="UTF-8"?> 
<AnimalList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Animal name="Don" id="1"/> 
    <Animal name="Mike"/> 
</AnimalList> 

powiązanych Informacje

można znaleźć następujące informacje przydatne:

Powiązane problemy