是否可以为所有Jersey资源方法指定默认视图?

时间:2016-02-29 04:34:20

标签: java spring jersey jackson

情况就是这样。

我有一个使用Jersey 2.17,Jackson 2.6.3和Spring 4.2.0的大型代码库。

我有很多模型,其中有一小部分属性用@JsonProperty公开。其余的被默认排除在外。

使用JsonView注释的的Jersey资源方法很多。

输入我。我需要编写一些新的内部API端点,这些端点公开内部/机密模型属性的不同子集。我已使用@JsonProperty@JsonView(SuperSecretAndInternal.class)注释了这些“私有”属性。

我添加了@JsonView(PublicForEveryone.class)注释的原始公开属性。

问题是有许多资源方法处理程序不使用指定JsonView。结果是暴露了所有属性(PublicForEveryone和SuperSecretAndIntenal)。

编辑。添加示例代码。

// POJO - before
@JsonAutoDetect(getterVisibility = NONE, isGetterVisibility = NONE, fieldVisibility = NONE)
class Person {

    @JsonProperty
    String name;
    @JsonProperty
    String age;

    Date createdDate;
    String socialSecurityNumber;

    // getters/setters not shown
}

这是在PublicAPIResource

中的Jersey方法处理程序中使用的
@GET
@Path("/people")
public Person getUser(@PathParam("name") String name)
{
// get user by name, return user
}

并生成json:

{ name: "Jane", age: 20 }

现在,我来了,并希望在备用和私有/内部API中公开POJO的敏感字段。所以我像这样修改POJO:

// POJO - after
@JsonAutoDetect(getterVisibility = NONE, isGetterVisibility = NONE, fieldVisibility = NONE)
class Person {

    @JsonProperty
    @JsonView(PublicForEveryone.class)
    String name;

    @JsonProperty
    @JsonView(PublicForEveryone.class)
    String age;

    @JsonProperty
    @JsonView(SuperSecretAndInternal.class)
    Date createdDate;

    @JsonProperty
    @JsonView(SuperSecretAndInternal.class)
    String socialSecurityNumber;

    // getters/setters not shown
}
创建视图时

public class Views
{

    public static class PublicForEveryone
    {}
    public static class SuperSecretAndInternal extends PublicForEveryone
    {}
}

我在PrivateAPIResource

中创建一个新的 Jersey资源处理程序
@GET
@Path("/internal/secret/people")
@JsonView( SuperSecretAndInternal.class )
public Person getUser(@PathParam("name") String name)
{
// get user by name, return user
}

返回json:

{ name: "Jane", age: 20, createdDate: xxx, socialSecuritynumber: 123  }

原始 PublicAPIResource现在返回整个Person POJO,因为它没有@JsonView注释。在这个简单的例子中,我可以简单地添加注释并完成,但在我的实际代码库中,有许多资源,更不用说People POJO是其他模型中的嵌套字段的实例。

问题:有没有办法为每个POJO /模型指定默认 JsonView?目的是如果一个jersey资源方法处理程序没有指定@JsonView,那么将使用默认值,而不是仅公开每个@JsonProperty带注释的属性。

如果没有,有没有人知道我可以实现的另一种方式,而不修改我的所有资源方法处理程序(因为我不能)?

我可以为POJO提供一个默认的序列化程序,使用“默认”视图对其进行序列化,但不知何故允许显式视图通过吗?

1 个答案:

答案 0 :(得分:0)

您可以配置默认包含/排除,但我认为这不会解决您的问题。您是否检查过JsonFilter http://wiki.fasterxml.com/JacksonFeatureJsonFilter,它具有定义的默认过滤器功能,可以应用于所有pojos / models。

示例pojo:

class Person{
    String name;
    String age;
    Date createdDate;
}
class User{
    String username;
    String password;
    Date createdDate;
}

CustomAnnotationInspector:

public class CustomIntrospector extends JacksonAnnotationIntrospector
{
  @Override
  public Object findFilterId(AnnotatedClass ac) {
    // Let's default to current behavior if annotation is found:
    Object id = super.findFilterId(ac);
    // but use simple class name if not
    if (id == null) {
       id = "DEFAULT_FILTER";
    }
    return id;
}

将其插入您的ObejctMapper:

ObjectMapper mapper = new ObjectMapper();

// create filter with id "DEFAULT_FILTER" and configure it to exclude 'createdDate' property.
FilterProvider filters = new SimpleFilterProvider().addFilter("DEFAULT_FILTER",
SimpleBeanPropertyFilter.serializeAllExcept("createdDate"));

JacksonAnnotationIntrospector jai = new CustomIntrospector ();

// plug the custom annotation that will use "DEFAULT_FILTER" if the pojo doesn't have @JsonFilter annotation.
String jsonPerson = mapper.setAnnotationIntrospector(jai).writer(filters).writeValueAsString(new Person());
String jsonUser = mapper.setAnnotationIntrospector(jai).writer(filters).writeValueAsString(new User());