objeto - ejercicios resueltos de clases abstractas en java
Alineación de una lista de objetos que implementan una interfaz común, con JaxB (2)
De acuerdo, si estás preparado para cambiar a Persona de una interfaz a una clase base abstracta, entonces estás satisfecho. Aquí está el código:
public class Main {
public static void main(String[] args) throws Exception {
Community community = new Community();
JAXBContext context = JAXBContext.newInstance(Community.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(community, System.out);
}
}
@XmlRootElement(name = "community")
@XmlSeeAlso({Person.class})
public class Community {
private List<Person> people;
@XmlElementWrapper(name="people")
@XmlElementRef()
public List<Person> getPeople() {
return people;
}
public Community() {
people = new ArrayList<Person>();
people.add(new Girl());
people.add(new Boy());
people.add(new Girl());
people.add(new Boy());
}
}
@XmlRootElement(name="boy")
public class Boy extends Person {
public String getName() {
return "John";
}
}
@XmlRootElement(name="girl")
public class Girl extends Person {
public String getName() {
return "Jane";
}
}
@XmlRootElement(name = "person")
@XmlSeeAlso({Girl.class,Boy.class})
public abstract class Person {
@XmlElement(name="name")
public abstract String getName();
}
El truco principal fue el uso de @XmlElementRef en la Lista de comunidad. Esto identifica el tipo de la clase a través de @XmlRootElement. También puede estar interesado en @XmlSeeAlso que ayuda a organizar las declaraciones de contexto.
Y la salida es
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<community>
<people>
<girl>
<name>Jane</name>
</girl>
<boy>
<name>John</name>
</boy>
<girl>
<name>Jane</name>
</girl>
<boy>
<name>John</name>
</boy>
</people>
</community>
Estoy tratando de ordenar una lista de objetos que implementan una interfaz común. Hay 3 clases y 1 interfaz involucrada:
Clase de comunidad (tiene un método: Lista <Persona> getPeople (); )
Interfaz de persona (tiene un método: String getName (); )
Clase de chica (implementa Persona)
Clase de chico (implementa Persona)
Vea el código a continuación.
Quiero un XML que se parece a esto:
<community>
<people>
<girl>
<name>Jane</name>
</girl>
<boy>
<name>John</name>
</boy>
<girl>
<name>Jane</name>
</girl>
<boy>
<name>John</name>
</boy>
</people>
</community>
o posiblemente:
<community>
<people>
<person>
<girl>
<name>Jane</name>
</girl>
</person>
<person>
<boy>
<name>John</name>
</boy>
</person>
</people>
</community>
Hasta ahora lo que obtengo es esto:
<community>
<people>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="girl">
<name>Jane</name>
</person>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="boy">
<name>John</name>
</person>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="girl">
<name>Jane</name>
</person>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="boy">
<name>John</name>
</person>
</people>
</community>
Me doy cuenta de que puedo cambiar el elemento a otra cosa, pero quiero que el nombre del elemento sea el nombre especificado en la clase Girl o Boy.
Se puede hacer esto? Gracias.
@XmlRootElement(name = "community")
public class Community {
private List<Person> people;
@XmlElementWrapper
@XmlElement(name="person")
public List<Person> getPeople() {
return people;
}
public Community() {
people = new ArrayList<Person>();
people.add(new Girl());
people.add(new Boy());
people.add(new Girl());
people.add(new Boy());
}
}
@XmlRootElement(name = "girl")
public class Girl implements Person {
@XmlElement
public String getName() {
return "Jane";
}
}
@XmlRootElement(name = "boy")
public class Boy implements Person {
@XmlElement
public String getName() {
return "John";
}
}
@XmlJavaTypeAdapter(AnyTypeAdapter.class)
public interface Person {
public String getName();
}
public class AnyTypeAdapter extends XmlAdapter<Object, Object> {
@Override
public Object marshal(Object v) throws Exception {
return v;
}
@Override
public Object unmarshal(Object v) throws Exception {
return v;
}
}
Para este escenario, recomendaría el uso de @XmlElements. @XmlElements se utiliza para representar el concepto de elección del esquema XML:
Así es como buscaría su ejemplo:
@XmlElements({
@XmlElement(name="girl", type=Girl.class),
@XmlElement(name="boy", type=Boy.class)
})
@XmlElementWrapper
public List<Person> getPeople() {
return people;
}
@XmlElementRef corresponde al concepto de grupos de sustitución en el esquema XML. Esta es la razón por la cual la respuesta previa requiere que la Persona sea cambiada de una interfaz a una clase.