¿Cómo anotar una lista usando @XmlElement?
Tengo la siguiente anotación usando javax.xml.bind.annotation.XmlElement
:
@XmlElement
public List<String> getKeywords() {
return keywords;
}
Que produce el siguiente XML cuando marshall algún contenido de ejemplo:
<keywords>keyword1</keywords>
<keywords>keyword2</keywords>
Me gustaría obtener el siguiente XML:
<keywords>
<keyword>keyword1</keyword>
<keyword>keyword2</keyword>
</keywords>
, ¿Qué tipo de anotación debo usar?
He intentado
@XmlElementWrapper
@XmlElement(name="keyword")
Pero entonces todo el contenido desaparece y el resultado es:{[14]]}
<keywords/>
Lo mismo sucede también si solo intento cambiar el nombre del elemento:
@XmlElement(name="keyword")
¿Qué estoy haciendo mal?
ACTUALIZACIÓN:
Aquí está el código completo actualizado para la clase de acuerdo con las primeras respuestas, pero todavía no funciona (el resultado es una lista vacía <keywords/>
cuando se marshalled a XML):
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
@XmlElementWrapper(name="keywords")
@XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
También probé lo siguiente con el mismo resultado:{[14]]}
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
@XmlElementWrapper(name="keywords")
@XmlElement(name="keyword")
private List<String> keywords;
public Content() {}
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
Sin embargo, las palabras clave no están vacías, ya que lo siguiente produce <keywords>keyword1</keywords><keywords>keyword2</keywords>
en lugar de una lista vacía:
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
@XmlElement
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
El código para marshalling es (JAX-RS):
import java.io.StringWriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@Path("process")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_XML)
public class ContentHandler {
@POST
public Response process(Content content) {
StringWriter stringWriter = new StringWriter();
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Content.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(content, stringWriter);
} catch (JAXBException e) {
return Response.serverError().entity(e.getMessage()).build();
}
return Response.ok(stringWriter.toString(), MediaType.APPLICATION_XML).build();
}
}
3 answers
Necesitas aprovechar @XmlElementWrapper
y @XmlElement
.
Modelo Java
Contenido
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Content {
private List<String> keywords;
public Content() {}
@XmlElementWrapper
@XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
Código de demostración
Demo
import java.util.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Content.class);
List<String> strings = new ArrayList<String>(2);
strings.add("foo");
strings.add("bar");
Content content = new Content();
content.setKeywords(strings);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(content, System.out);
}
}
Salida
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
<keywords>
<keyword>foo</keyword>
<keyword>bar</keyword>
</keywords>
</content>
Para Más Información
A continuación hay enlaces a un par de artículos de mi blog que proporcionan adicional información:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-19 14:04:07
Utilice este formulario:
@XmlElementWrapper(name="keywords")
@XmlElement(name="keyword")
Tenga en cuenta que si keywords
está vacío entonces obtendrá <keywords />
.
A veces necesitará agregar @XmlRootElement
a su clase (depende del contexto) y la anotación @XmlAccessorType(XmlAccessType.?)
. Normalmente uso @XmlAccessorType(XmlAccessType.FIELD)
y anoto mis campos con @XmlElement
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-19 12:54:09
La respuesta anterior de - Blaise Doughan es completamente correcta
Otra forma sencilla es, incluso si no escribes el - @XmlElementWrapper
private List<String> keywords;
@XmlElementWrapper
@XmlElement(name="keyword")
public List<String> getKeywords() {
return keywords;
}
Puede usarlo de esta manera: escriba el XmlAccessorType a nivel de clase, luego el nombre del elemento XML será el mismo que el nombre del miembro de la clase-keywords
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
private List<String> keywords;
public Content() {}
public List<String> getKeywords() {
return keywords;
}
public void setKeywords(List<String> keywords) {
this.keywords = keywords;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-06 15:25:13