xmljson unmarshal marshal example camel java json rest jersey unmarshalling

java - xmljson - camel unmarshal example



cómo usar alguna indirección al desasignar json a Java Bean usando Jersey usando anotaciones jaxb (2)

Estoy intentando deshacerme de algunos json recibidos (del servicio web de Jira restful).

El problema es: un "problema" tiene una propiedad de "resumen" y una lista de campos.

El resumen no está presente como un atributo en el json recibido, sino como un valor del atributo "campos". Insisto en desarticular esta estructura:

@XmlRootElement class Issue { String summary; List<Field> fields; // getters/setters and lots of other fields }

Recibido JSON:

{ "expand":"html", "self":"https://example.com/jira/rest/api/latest/issue/XYZ-1234", "key":"XYZ-1234", "fields": { "summary": { "name":"summary", "type":"java.lang.String", "value":"test 1234" }, "customfield_10080": { "name":"Testeur", "type":"com.atlassian.jira.plugin.system.customfieldtypes:userpicker" }, "status": { "name":"status", "type":"com.atlassian.jira.issue.status.Status", "value": { "self":"https://example.com/jira/rest/api/latest/status/5", "name":"Resolved" } }, ... }, "transitions":"https://example.com/jira/rest/api/latest/issue/XYZ-1234/transitions" }

No quiero usar el propio cliente de Jira (demasiadas dependencias que no quiero en mi aplicación).

editar: le pregunté a mi pregunta de otra manera para intentar aclarar: cómo mapear una estructura de frijoles a un esquema diferente con jax-rs


La clase anotada debe ser biyectiva: debe permitir generar la misma entrada de la que no se ha ordenado. Si aún desea usar un gráfico de objetos no biyectivos, puede usar @XmlAnyElement la siguiente manera:

public class Issue { @XmlElement(required = true) protected Fields fields; public Fields getFields() { return fields; } }

En la entrada que dio, los campos no son una lista, sino un campo (JSON usa [] para delimitar listas):

public class Fields { @XmlElement(required = true) protected Summary summary; @XmlAnyElement private List<Element> fields; public List<Element> getFields() { return fields; } public Summary getSummary() { return summary; } }

Para capturar el resumen, deberá definir una clase dedicada. Los campos restantes se agruparán en la lista de elementos de los fields .

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

A continuación, una prueba de unidad con su entrada muestra que todo funciona:

public class JaxbTest { @Test public void unmarshal() throws JAXBException, IOException { URL xmlUrl = Resources.getResource("json.txt"); InputStream stream = Resources.newInputStreamSupplier(xmlUrl).getInput(); Issue issue = parse(stream, Issue.class); assertEquals("summary", issue.getFields().getSummary().getName()); Element element = issue.getFields().getFields().get(0); assertEquals("customfield_10080", element.getTagName()); assertEquals("name", element.getFirstChild().getLocalName()); assertEquals("Testeur", element.getFirstChild().getFirstChild().getTextContent()); } private <T> T parse(InputStream stream, Class<T> clazz) throws JAXBException { JSONUnmarshaller unmarshaller = JsonContextNatural().createJSONUnmarshaller(); return unmarshaller.unmarshalFromJSON(stream, clazz); } private JSONJAXBContext JsonContextNatural() throws JAXBException { return new JSONJAXBContext(JSONConfiguration.natural().build(), Issue.class); } }

Estas pruebas muestran que sin usar clases dedicadas, su código será difícil de leer rápidamente.

Necesitarás esas dependencias maven para ejecutarlo:

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>r08</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.6</version> </dependency>


{ "expand":"html", "self":"xxx/jira/rest/api/latest/issue/EPC-2731";, "key":"EPC-2731", "fields":{ "summary":{ "name":"summary", "type":"java.lang.String", "value":"Fwd: commentaires vides dans FicheSousGroupement" }, "timetracking":{ "name":"timetracking", "type":"com.atlassian.jira.issue.fields.TimeTrackingSystemField", "value":{ "timeestimate":0, "timespent":60 } }, "issuetype":{ "name":"issuetype", "type":"com.atlassian.jira.issue.issuetype.IssueType", "value":{ "self":"xxx/jira/rest/api/latest/issueType/2";, "name":"Nouvelle fonctionnalité", "subtask":false } }, "customfield_10080":{ "name":"Testeur", "type":"com.atlassian.jira.plugin.system.customfieldtypes:userpicker" },