为不同的Jersey REST服务调用应用不同的Jackson过滤器

Thi*_*kel 13 java jax-rs jersey jackson

我使用Jersey来实现JAX-RS REST样式服务以及用于JSON映射的Jackson 2.0.2.其中一个REST服务返回一个List<EntityA>(让我们称之为indexA)EntityA包含List<EntityB>另一个服务,而另一个服务只返回一个List<EntityB>(让我们称之为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() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是将Jackson过滤器应用于indexA调用,以便不是所有子EntityB元素的属性都被序列化.OTOH indexB应该EntityB完整回归.

我知道a的存在ContextResolver<ObjectMapper>,我已经将其用于其他目的.不幸的是,对于ContextResolver这似乎是不可能区分这两种服务调用的Class供给ContextResolver.getContext(Class)ArrayList在两种情况下(和感谢类型擦除我想不通泛型类型参数).

是否有更适合配置ObjectMapper/ FilterProvider取决于正在映射的实体类型的钩子?

我可以使用如何使用Java返回部分JSON响应中提出的方法:手动映射到a String,但这会杀死基于声明性注释的方法的整体美,所以我想避免这种情况.

Joh*_*ing 29

我经历了同样的情况,经过大量的研究,我想通了,解决方案是使用@JsonView和Spring可以注入ObjectMapperJSON Writer而不会杀死泽西的美丽.

我正在研究一组REST API,我想获得一个SystemObject特定实例的实例列表和详细信息SystemObject,就像你只需要列表中每个实例的非常有限的属性数量以及一些其他属性细节,我只为它们定义视图,并在SystemObject类中添加注释.但默认情况下,没有@JsonView注释的所有属性都将输出到JSON,但item(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION)我可以使用一种配置来排除它们.

问题是我必须将其设置为true以满足我的需要.但是我无法改变ObjectMapper,它通过阅读下面的3篇文章来实现将对象转换为JSON的魔力,我认为我能做的唯一方法就是将一个Modified注入ObjectMapper到Jersey.现在我得到了我想要的东西.

就像您为数据库表创建多个视图一样.

这三个链接将以不同的方式为您提供帮助:

如何创建一个可以被Spring用来注入的ObjectMapperProvider

泽西,杰克逊,春天和JSON

Jersey + Spring集成示例

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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

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...

}
Run Code Online (Sandbox Code Playgroud)

REST模型视图:

package com.john.rest.model;

public class SystemObjectView {
    public static class ObjectList { };

    public static class ObjectDetail extends ObjectList { }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我能投票20次,我会.在我阅读本文之前,我不知道您可以将JsonView应用于Jersey资源方法以选择要序列化的视图.如果在文档中描述了我完全错过了它.BTW - 没有Spring的工作(我使用的是Felix).非常感谢! (4认同)