I am using Jersey to implement JAX-RS REST-style services along with Jackson 2.0.2 for the JSON mapping. One of these REST services returns a List<EntityA>
(let's call it indexA
) where EntityA
contains another List<EntityB>
whereas another service just returns a List<EntityB>
(let's call it indexB
):
@Entity
@JsonAutoDetect
public class EntityA {
@Id
private String id;
@OneToMany
private List<EntityB> b;
...
}
@Entity
@JsonAutoDetect
@JsonFilter("bFilter")
public class EntityB {
@Id
private String id;
private String some;
private String other;
private String attributes;
...
}
@Path("/a")
public class AResource {
@GET
@Path("/")
public List<EntityA> indexA() {
...
}
}
@Path("/b")
public class BResource {
@GET
@Path("/")
public List<EntityB> indexB() {
...
}
}
What I'd like to achieve is to apply a Jackson filter to the indexA
invocation so that not all attributes of the child EntityB
elements are serialized. OTOH, indexB
should return EntityB
in its completeness.
I am aware of the existence of a ContextResolver<ObjectMapper>
, which I am already using for other purposes. Unfortunately, for the ContextResolver
it seems to be impossible to distinguish both service invocations as the Class
supplied to ContextResolver.getContext(Class)
is ArrayList
in both cases (and thanks to type erasure I cannot figure out the generic type parameters).
Are there any hooks better suited at configuring an ObjectMapper
/FilterProvider
depending on the entity type that is being mapped?
I could use the approach proposed in How to return a partial JSON response using Java?: Manually mapping to a String
, but that kills the whole beauty of a declarative annotation-based approach, so I'd like to avoid this.
I was in the same situation, after tons of research, I figured it out, the solution is to use @JsonView
and Spring which can inject an ObjectMapper
into the JSON Writer without killing the beauty of Jersey.
I am working on a set of REST APIs, I want to get a list of instances of SystemObject
and the detail a specific instance of SystemObject
, just like you I just want very limited of number of properties of each instance in the list and some additional properties in the detail, I just define Views for them, and add annotation in the SystemObject
class. but by default, all properties with no @JsonView
annotation will be output to the JSON, but there is a configuration item(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION)
I can use to exclude them.
The problem is that I have to set it to true to meet my need. but I can not change the ObjectMapper which does the magic to convert the object to JSON, by reading the 3 articles below, I got the idea that the only way I can do is to inject a Modified ObjectMapper
to Jersey.
Now I got what I want.
It is like you create multiple views against a database table.
These 3 links will help you in different ways:
How to create a ObjectMapperProvider which can be used by Spring to inject
Jersey, Jackson, Spring and JSON
Jersey + Spring integration example
REST resource:
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);
}
}
}
REST model:
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...
}
REST model view:
package com.john.rest.model;
public class SystemObjectView {
public static class ObjectList { };
public static class ObjectDetail extends ObjectList { }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With