java json jaxb jersey

java - Generando más json como json de JAXB y Jersey



(5)

Trabajo con un modelo de datos creado con JAXB, de ahí puedo generar XML directamente

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>/ <metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0"> <artist-list offset="0" count="1"> <artist ext:score="100" type="Group" id="4302e264-1cf0-4d1f-aca7-2a6f89e34b36"> <name>Farming Incident</name> <ipi-list> <ipi>1001</ipi> </ipi-list> </artist> </artist-list> </metadata>

y con la ayuda de Jersey también generan JSon usando notación Natural

"artist-list": {"offset":0, "count":1, "artist":[ {"score":"100", "type":"Group", "id":"4302e264-1cf0-4d1faca7-2a6f89e34b36", "name":"Farming Incident", "ipi-list": { "ipi":[ "1001" ] } }] }

El Xml está bien, el json está casi bien, excepto porque como Json admite directamente matrices con elementos como ipi-list y artist-list, no parece muy json, ¿es posible generar más json como json de mi modelo?

Información adicional solicitada La json se genera a partir de este esquema de MMD http://svn.musicbrainz.org/mmd-schema/trunk/brainz-mmd2-jaxb/src/main/resources/musicbrainz_mmd-2.0.xsd utilizando JAXB y Jersey, ver http://svn.musicbrainz.org/search_server/trunk/servlet/src/main/java/org/musicbrainz/search/servlet/mmd2/ResultsWriter.java y http://svn.musicbrainz.org/search_server/trunk /servlet/src/main/java/org/musicbrainz/search/servlet/mmd2/ArtistWriter.java

El punto es que quiero poder generar Json y XML desde un esquema con el mínimo de alboroto, pero aparentemente el Json no se ve bien así que estoy buscando una manera de mejorarlo (realmente no tengo ninguna experiencia de json yo mismo)


El JSON creado por Jersey es una representación exacta de JSOON de ese modelo provisto en el sitio. El problema al que se enfrentan aquí es que el sitio proporciona un modelo de datos incómodo, no que el marco no esté haciendo lo correcto.

¿Por qué este servicio devuelve un objeto de tipo lista de artistas en lugar de devolver una lista de artistas? ¿Por qué el servicio tiene un objeto ipi-list también? La verdadera pregunta que debería hacerse es cómo debe modelarse para que funcione mejor con todas las tecnologías.


Creo que el problema que está viendo con ipiList se debe a un problema con las matrices / listas de elementos individuales en una biblioteca subyacente que Jersey utiliza para mapear a JSON.

La siguiente publicación de blog (no la mía) muestra una forma de configurar Jersey, y los comentarios se vinculan con formas alternativas (posiblemente más simples) de hacer que la representación JSON sea correcta para las matrices:

http://tugdualgrall.blogspot.co.uk/2011/09/jax-rs-jersey-and-single-element-arrays.html


Personalmente, no me gustan mucho las anotaciones. Tener el hábito de generar JSON / XML en código simple. :)

Por ejemplo, con Jackson (Gson también similar):

mapper = new ObjectMapper(); JsonNode root = mapper.createObjectNode(); JsonNode artist = mapper.createObjectNode(); artist.put("score", "100"); root.put("artist-list", artist); ArrayNode ipiList = mapper.createArrayNode(); ipi.add("1001"); artist.put("ipi-list", ipiList);

Puede parecer mucho trabajo en la superficie. Pero para mí esta es una forma muy clara de mapear JSON a los objetos. Básicamente tener mi método habitual en las clases de entidades es el método Json (). Aquí hay un ejemplo: https://github.com/richardzcode/metrics/blob/master/src/main/java/com/rz/metrics/core/entities

Solo soy yo.

Para JAXB, creo que necesita anotar su entidad como se muestra a continuación:

@XmlElement(name = "ipi-list") private List<Ipi> ipi;


Nota: Soy el líder de EclipseLink JAXB (MOXy) y miembro del grupo de expertos JAXB (JSR-222) .

Puede aprovechar el documento JSON-Binding y el mapeo externo en EclipseLink JAXB (MOXy) para respaldar su caso de uso.

Archivo de mapeo externo (oxml.xml)

Puede usar la @XmlPath(".") En MOXy para aplanar partes de su modelo de objetos. Especifique una ruta de "." le dice a MOXy que incluya el objeto al que se hace referencia en el nodo padre.

<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="forum10699038"> <java-types> <java-type name="Metadata"> <java-attributes> <xml-element java-attribute="artistList" xml-path="."/> </java-attributes> </java-type> <java-type name="Artist"> <java-attributes> <xml-element java-attribute="ipiList" xml-path="."/> </java-attributes> </java-type> </java-types> </xml-bindings>

jaxb.properties

Para especificar MOXy como su proveedor JAXB, necesita agregar un archivo llamado jaxb.properties en el mismo paquete que su modelo de dominio con la siguiente entrada.

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Manifestación

El siguiente código rellena el modelo de objetos de su documento XML y luego se agrupa en JSON. Demuestra cómo aprovechar el archivo de mapeo externo y poner MOXy en modo JSON.

package forum10699038; import java.io.File; import java.util.*; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextProperties; public class Demo { public static void main(String[] args) throws Exception { // READ FROM XML JAXBContext jcXML = JAXBContext.newInstance(Metadata.class); File xml = new File("src/forum10699038/input.xml"); Unmarshaller unmarshaller = jcXML.createUnmarshaller(); Metadata metadata = (Metadata) unmarshaller.unmarshal(xml); // WRITE TO JSON Map<String, Object> properties = new HashMap<String, Object>(3); properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum10699038/oxm.xml"); properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jcJSON = JAXBContext.newInstance(new Class[] {Metadata.class}, properties); Marshaller marshaller = jcJSON.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(metadata, System.out); } }

Salida

{ "artist" : [ { "id" : "4302e264-1cf0-4d1f-aca7-2a6f89e34b36", "type" : "Group", "score" : "100", "name" : "Farming Incident", "ipi" : [ "1001" ] } ] }

MOXy y Jersey

Puede usar MOXy fácilmente como su proveedor JSON en un entorno JAXB-RS como Jersey:

OTROS ARCHIVOS

A continuación se encuentran las versiones de sus archivos que creé para asegurarse de que todo funcionara correctamente.

input.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#" xmlns:ext="http://musicbrainz.org/ns/ext#-2.0"> <artist-list offset="0" count="1"> <artist ext:score="100" type="Group" id="4302e264-1cf0-4d1f-aca7-2a6f89e34b36"> <name>Farming Incident</name> <ipi-list> <ipi>1001</ipi> </ipi-list> </artist> </artist-list> </metadata>

Metadata

package forum10699038; import javax.xml.bind.annotation.*; @XmlRootElement public class Metadata { @XmlElement(name="artist-list") ArtistList artistList; }

ArtistList

package forum10699038; import java.util.List; public class ArtistList { private List<Artist> artist; }

Artista

package forum10699038; import javax.xml.bind.annotation.*; @XmlType(propOrder={"name", "ipiList"}) public class Artist { @XmlAttribute private String id; @XmlAttribute private String type; @XmlAttribute(namespace="http://musicbrainz.org/ns/ext#-2.0") private String score; @XmlElement(name="ipi-list") private IPIList ipiList; private String name; }

IPList

package forum10699038; import java.util.List; public class IPIList { private List<String> ipi; }

paquete-información

@XmlSchema( namespace = "http://musicbrainz.org/ns/mmd-2.0#", elementFormDefault = XmlNsForm.QUALIFIED, xmlns={ @XmlNs(prefix="", namespaceURI = "http://musicbrainz.org/ns/mmd-2.0#") } ) @XmlAccessorType(XmlAccessType.FIELD) package forum10699038; import javax.xml.bind.annotation.*;


Logré resolver una matriz JSON y un "error" de campo primitivo en la biblioteca Jersey json. El ingrediente secreto se menciona previamente JSONConfiguration y ContextResolver magic. Ver mi publicación siguiente tiene un ejemplo de código completo, ContextResolver personalizada y la clase de aplicación de reposo puede ser lógica algo difusa a primera vista.

Cómo serializar primitivos de Java utilizando Jersey REST

  • json array para listas Java de un solo elemento o cero
  • primitivo entero o campos booleanos sin caracteres de comillas