Comment puis-je personnaliser la sérialisation d'une liste de JAXB objets JSON?
Je suis en utilisant le Maillot de créer un service web REST pour un composant serveur.
La JAXB-annoté objet que je veux pour sérialiser dans une liste ressemble à ceci:
@XmlRootElement(name = "distribution")
@XmlType(name = "tDistribution", propOrder = {
"id", "name"
})
public class XMLDistribution {
private String id;
private String name;
//no-args constructor, getters, setters, etc
}
J'ai un RESTE de ressources pour récupérer une distribution qui ressemble à ceci:
@Path("/distribution/{id: [1-9][0-9]*}")
public class RESTDistribution {
@GET
@Produces("application/json")
public XMLDistribution retrieve(@PathParam("id") String id) {
return retrieveDistribution(Long.parseLong(id));
}
//business logic (retrieveDistribution(long))
}
J'ai aussi un RESTE de ressources pour récupérer une liste de toutes les distributions, qui ressemble à ceci:
@Path("/distributions")
public class RESTDistributions {
@GET
@Produces("application/json")
public List<XMLDistribution> retrieveAll() {
return retrieveDistributions();
}
//business logic (retrieveDistributions())
}
- Je utiliser un ContextResolver pour personnaliser JAXB la sérialisation, qui est actuellement configuré comme ceci:
@Provider
@Produces("application/json")
public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
public JAXBJSONContextResolver() throws Exception {
JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped();
b.nonStrings("id");
b.rootUnwrapping(true);
b.arrays("distribution");
context = new JSONJAXBContext(b.build(), XMLDistribution.class);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return context;
}
}
Les deux RESTE des ressources de travail, ainsi que le contexte de résolution. Ceci est un exemple de sortie pour le premier:
//path: /distribution/1
{"id":1,"name":"Example Distribution"}
Qui est exactement ce que je veux. Ceci est un exemple de sortie de la liste:
//path: /distributions
{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}
Qui n'est pas tout à fait ce que je veux.
Je ne comprends pas pourquoi il y a un enfermant distribution
balise là. J'ai voulu l'enlever avec .rootUnwrapping(true)
dans le contexte de résolution, mais apparemment ce ne supprime une autre balise englobante. C'est la sortie avec .rootUnwrapping(false)
:
//path: /distribution/1
{"distribution":{"id":1,"name":"Example Distribution"}} //not ok
//path: /distributions
{"xMLDistributions":{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}}
J'ai également eu à configurer .arrays("distribution")
de toujours obtenir un tableau JSON, même avec un seul élément.
Idéalement, j'aimerais avoir cette sortie:
//path: /distribution/1
{"id":1,"name":"Example Distribution"} //currently works
//path: /distributions
[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]
J'ai essayé de retourner un List<XMLDistribution>
, un XMLDistributionList
(wrapper autour d'une liste), un XMLDistribution[]
, mais je ne pouvais pas trouver un moyen d'obtenir un simple tableau JSON de distributions dans mon format requis.
J'ai aussi essayé les autres notations retourné par JSONConfiguration.natural()
, JSONConfiguration.mappedJettison()
, etc, et ne pouvait pas obtenir quelque chose ressemblant à ce que j'ai besoin.
Personne ne sait si il est possible de configurer JAXB pour ce faire?
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé une solution: remplacer le JAXB sérialiseur JSON avec un meilleur comportement sérialiseur JSON comme Jackson. Le plus simple est d'utiliser jackson-jaxrs, qui a déjà fait pour vous. La classe est JacksonJsonProvider. Tout ce que vous avez à faire est de modifier votre projet web.xml de sorte que Jersey (ou un autre JAX-RS de la mise en œuvre des analyses pour elle. Voici ce que vous devez ajouter:
Et c'est tout là est à lui. Jackson sera utilisé pour la sérialisation JSON, et il fonctionne de la même façon que vous attendez pour les listes et les tableaux.
Un chemin plus long est d'écrire votre propre MessageBodyWriter enregistré à produire "application/json". Voici un exemple:
Vous aurez besoin pour vous assurer que votre web.xml comprend le paquet, comme pour le prêt-à-solution ci-dessus.
De la manière suivante: le tour est joué! Vous verrez correctement formé JSON.
Vous pouvez télécharger Jackson à partir d'ici:
http://jackson.codehaus.org/
init-param
solution fonctionne dans la Jetée au cours de mon développement local, il ne fonctionne pas lors de son déploiement sur Websphere. Cependant, votre deuxième solution fonctionne très bien.La réponse de Jonhatan est grand et il a été très utile pour moi.
Juste une mise à niveau:
si vous utilisez la version 2.x de Jackson (par exemple, la version 2.1) la classe est com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider, donc la web.xml est: