Accès à Jackson Object Mapper dans RestEasy
on m'a demandé d'embellir Jackson JSON par défaut à partir d'un point final RestEasy. J'ai fait quelques recherches sur Jackson et j'ai écrit du code autonome pour pouvoir supprimer les nulls, personnaliser les formats de données, etc. Maintenant le défi est d'injecter ce code dans la sérialisation JSON de RestEasy.
a en juger par les billets du forum c'est trivial au printemps, cependant ça ne semble pas être le cas en RestEasy. J'ai écrit un ContextResolver et configuré comme resteasy.fournisseur de contexte params dans Web.xml (sur Tomcat) mais qui empêche le webapp de charger sur Tomcat.
maintenant j'essaie d'étendre javax.ws.rs.noyau.Application et fournir un Contexterésolver mais ne faisant aucun progrès. Est-ce normal, quelqu'un a fait cela? Toute aide est grandement appréciée.
6 réponses
Ok, j'ai compris, j'ai pu le faire en écrivant un JacksonJsonProvider personnalisé basé sur le Jackson FAQ: JAX-RS.Le code est comme suit:
@Provider
public class QBOJacksonJsonProvider extends JacksonJsonProvider {
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Override
public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
Log.info(getClass(), "In custom JSON provider");
//get the Object Mapper
ObjectMapper mapper = locateMapper(type, mediaType);
// Suppress null properties in JSON output
mapper.getSerializationConfig().setSerializationInclusion(org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_NULL);
// Set human readable date format
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
mapper.getSerializationConfig().setDateFormat(sdf);
super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);
}
}
j'ai trouvé une meilleure façon de modifier la SerializationConfig de Jackson - vous pouvez intercepter la création ObjectMapper en utilisant un JAX-RS ContextResolver.
@Provider
@Produces(Array(MediaType.APPLICATION_JSON))
class JacksonConfig extends ContextResolver[ObjectMapper] {
val mapper = new ObjectMapper()
mapper.getSerializationConfig.setSerializationInclusion(Inclusion.NON_NULL)
def getContext(objectType: Class[_]) = mapper
}
vous devez vous inscrire à RESTEasy de l'une des façons suivantes:
- le retourner sous forme de classe ou d'instance à partir d'un javax.ws.rs.noyau.Application implementation
- listez-le comme fournisseur de resteasy.les fournisseurs
- laissez RESTEasy le scanner automatiquement dans votre guerre fichier. Voir Le Guide De Configuration
- l'ajouter manuellement via ResteasyProviderFactory.getInstance().registerProvider(Class) or registerprovider instance (Object)
Référence: RESTEasy docs
Référence: Nicklas Karlsson sur les forums JBoss
Veuillez noter que cela fonctionne avec RESTEasy 2.3.2 livré avec un module dans JBoss 7.1.1.Final, mais ne semble pas fonctionner avec RESTEasy 3.0-beta5.
Fournisseur pour Jackson ObjectMapper
devrait être la façon standard JAX-RS de faire cela (fonctionne avec Jersey), donc il semble que la façon d'aller avec RESTeasy aussi bien.
si vous utilisez le fournisseur Jackson2, vous devez faire quelque chose de légèrement différent de la réponse précédente. Cet exemple va Imprimer la sortie par défaut
@Provider
public class JSONProvider extends ResteasyJackson2Provider {
@Override
public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType json, MultivaluedMap<String, Object> headers, OutputStream body) throws IOException {
ObjectMapper mapper = locateMapper(type, json);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
super.writeTo(value, type, genericType, annotations, json, headers, body);
}
}
et l'enregistrer dans votre web-xml, si vous n'avez pas autoregister, l'ajouter à votre resteasy.fournisseurs contexte-param
Si vous utilisez le Jackson 2.2.X fournisseur, Resteasy a fourni un impression d'annotation) des nouvelles à la une de JAXB fournisseur de:
org.jboss.resteasy.annotations.providers.jackson.Formatted
Voici un exemple:
@GET @Produces("application/json") @Path("/formatted/{id}") @Formatted public Product getFormattedProduct() { return new Product(333, "robot"); }
comme l'exemple ci-dessus, l'annotation formatée par @activera sous-jacent à L'option Jackson " SerializationFeature.INDENT_OUTPUT".
Ce n'est pas une solution globale, mais vous peut mettre l'annotation sur les classes trop.
j'ai eu beaucoup de travail pour l'enregistrer dans mon application, même en suivant le Conseil d'utiliser le context-param une fois que j'utilise la botte de printemps et n'ai pas le web.xml, voici ce que j'ai fait
fournisseur sur mesure
package com.mageddo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
@Provider
@Consumes({"application/json", "application/*+json", "text/json"})
@Produces({"application/json", "application/*+json", "text/json"})
public class CustomJacksonJsonProvider extends ResteasyJackson2Provider {
private ObjectMapper objectMapper = new ObjectMapper(); // my own object mapper
@Override
public ObjectMapper locateMapper(Class<?> type, MediaType mediaType) {
return objectMapper;
}
}
S'inscrire sur demande
META-INF/services / javax.ws.rs.ext.Fournisseurs
com.mageddo.CustomJacksonJsonProvider
org.jboss.resteasy.plugins.providers.jackson.UnrecognizedPropertyExceptionHandler