Can JAXB initialize values ​​in base classes?

I am working on a Scala project, and we want to use XML to initialize our objects using JAXB (not Spring). I have a hierarchy in which additional data members are added to subclasses. A simple example would look something like this:

class Animal { string name } class Cat extends Animal { int numLives } class Dog extends Animal { bool hasSpots } 

I would like to be able to initialize a list of animals from an XML block that looks something like this:

 <Animals> <Cat> <name>Garfield</name> <numLives>9</numLives> </Cat> <Dog> <name>Odie</name> <hasSpots>false</hasSpots> </Dog> </Animals> 

How can we customize annotations in classes to be able to handle this?

+6
source share
2 answers

In this example, you will want to use the annotations @XmlElementRef and @XmlRootElement . This is consistent with the concept of XML wildcard schemas. This will allow you to have a list of objects from the inheritance hierarchy differentiated by element.

Animals

This will serve as the root object for the domain model. It has a List property annotated with @XmlElementRef . This means that it will match the values ​​based on the value of their @XmlRootElement annotations.

 package forum8356849; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement(name="Animals") @XmlAccessorType(XmlAccessType.FIELD) @XmlSeeAlso({Cat.class, Dog.class}) public class Animals { @XmlElementRef private List<Animal> animals; } 

Animal

 package forum8356849; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) class Animal { String name; } 

Cat

We annotate the Cat class using the @XmlRootElement annotation. This is used in tandem with the @XmlElementRef annotation on Animals .

 package forum8356849; import javax.xml.bind.annotation.*; @XmlRootElement(name="Cat") class Cat extends Animal { int numLives; } 

Dog

We will also add the @XmlRootElement annotation to the Dog class.

 package forum8356849; import javax.xml.bind.annotation.*; @XmlRootElement(name="Dog") class Dog extends Animal { boolean hasSpots; } 

Demo

You can use the following class to see that everything works as expected. input.xml matches the XML provided in your question.

 package forum8356849; import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Animals.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum8356849/input.xml"); Animals animals = (Animals) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(animals, System.out); } } 

For additional information

+3
source

In such cases, I prefer to create an XSD scheme and generate code from it, so you are safe. But to answer your question, yes, you can. Annotations - XMLElement, XMLAttribute, XMLRootElement.

0
source

Source: https://habr.com/ru/post/902930/


All Articles