Estaba en la misma situación, después de toneladas de investigación, lo descubrí, la solución es usar @JsonView
y Spring que puede inyectar un ObjectMapper
en el escritor JSON sin matar la belleza de Jersey.
estoy trabajando en un conjunto de APIs REST, quiero obtener una lista de instancias de SystemObject
y el detalle de una instancia específica de SystemObject
, al igual que sólo quiero muy limitado de número de propiedades de cada instancia en el lista y algunas propiedades adicionales en el detalle, solo defino Vistas para ellas y agrego anotaciones en la clase SystemObject
. pero de forma predeterminada, todas las propiedades sin anotación @JsonView
se enviarán a JSON, pero hay una configuración item(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION)
que puedo usar para excluirlas.
El problema es que tengo que configurarlo para cumplir con mis necesidades. pero no puedo cambiar el ObjectMapper que hace la magia para convertir el objeto a JSON, leyendo los 3 artículos a continuación, tengo la idea de que la única manera que puedo hacer es inyectar un Modificado ObjectMapper
a Jersey. Ahora tengo lo que quiero.
Es como crear varias vistas en una tabla de base de datos.
Estos 3 enlaces le ayudará en diferentes formas:
How to create a ObjectMapperProvider which can be used by Spring to inject
Jersey, Jackson, Spring and JSON
Jersey + Spring integration example
recursos REST:
package com.john.rest.resource;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import org.codehaus.jackson.map.annotate.JsonView;
import org.springframework.stereotype.Component;
import com.midtronics.esp.common.EspException;
import com.midtronics.esp.common.SystemObject;
import com.midtronics.esp.mobile.model.SystemObjectView;
import com.midtronics.esp.model.accesscontrol.AccessControlBean;
import com.midtronics.esp.model.site.SiteBean;
@Component
@Path("/hierarchy")
public class Hierarchy {
// Allows to insert contextual objects into the class,
// e.g. ServletContext, Request, Response, UriInfo
@Context
UriInfo uriInfo;
@Context
Request request;
// Return the list of sites
@GET
@Path("sites")
@Produces(MediaType.APPLICATION_JSON)
@JsonView({SystemObjectView.ObjectList.class})
public List<SystemObject> listSite(
@HeaderParam("userId") String userId,
@HeaderParam("password") String password) {
ArrayList<SystemObject> sites= new ArrayList<SystemObject>();
try{
if(!AccessControlBean.CheckUser(userId, password)){
throw new WebApplicationException(401);
}
SystemObject.GetSiteListByPage(sites, 2, 3);
return sites;
} catch(EspException e){
throw new WebApplicationException(401);
} catch (Exception e) {
throw new WebApplicationException(500);
}
}
// Return the number of sites
@GET
@Path("sites/total")
@Produces(MediaType.TEXT_PLAIN)
public String getSiteNumber(@HeaderParam("userId") String userId,
@HeaderParam("password") String password) {
try{
return Integer.toString(SiteBean.GetSiteTotal());
} catch(EspException e){
throw new WebApplicationException(401);
} catch (Exception e) {
throw new WebApplicationException(500);
}
}
}
modelo REST:
package com.john.rest.model;
import java.io.Serializable;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlRootElement;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonView;
import com.midtronics.esp.mobile.model.SystemObjectView;
import com.midtronics.esp.model.common.ICommonDAO;
@XmlRootElement
public class SystemObject implements Serializable
{
private static final long serialVersionUID = 3989499187492868996L;
@JsonProperty("id")
@JsonView({SystemObjectView.ObjectList.class, SystemObjectView.ObjectDetail.class})
protected String objectID = "";
@JsonProperty("parentId")
protected String parentID = "";
@JsonProperty("name")
@JsonView({SystemObjectView.ObjectList.class, SystemObjectView.ObjectDetail.class})
protected String objectName = "";
//getters...
//setters...
}
RESTO vista del modelo:
package com.john.rest.model;
public class SystemObjectView {
public static class ObjectList { };
public static class ObjectDetail extends ObjectList { }
}
Si pudiera votar a esto 20 veces que lo haría. Hasta que leí esto, no tenía idea de que pudiera aplicar JsonView al método de recursos Jersey para seleccionar la vista para serializar. Si eso está descrito en los documentos, lo extrañé por completo. Por cierto, funciona sin Spring (estoy usando Felix). ¡Muchas gracias! – sfitts
No creo que te hayas perdido esto en los documentos. He estado buscando una buena manera de hacer esto durante mucho tiempo, y nunca encontré uno hasta que vi esta publicación. –
Gracias a su informe, el proyecto README ahora incluye una breve descripción de las anotaciones que son aplicables a los puntos finales JAX-RS - https://github.com/FasterXML/jackson-jaxrs-providers - y con suerte otros contenedores (Spring, Restlet) tener/agregar algo similar. – StaxMan