如何排除Jackson不使用注释的字段?

时间:2021-07-31 18:02:27

I need to exclude some fields by names before rendering. The list of fields is dynamic, so I can't use annotations.

在渲染之前,我需要通过名称排除一些字段。字段列表是动态的,所以我不能使用注释。

I've tried to create custom serializer but I can't get field name there.

我尝试过创建自定义序列化器,但是我不能在那里获得字段名。

In GSON I've used ExclusionStrategy, but Jackson has no such functionality. Is there an equivalent?

在GSON,我使用了排他性策略,但是Jackson没有这种功能。有一个等价的吗?

5 个解决方案

#1


27  

The below example of excluding fields by name is from my blog post, Gson v Jackson - Part 4. (Search for the PropertyFilterMixIn.) This example demonstrates using a FilterProvider with a SimpleBeanPropertyFilter to serializeAllExcept a user-specified list of field names.

下面的例子是我的博客文章,Gson诉Jackson -第4部分。(寻找PropertyFilterMixIn。)这个示例演示了如何使用带有SimpleBeanPropertyFilter的FilterProvider来序列化一个用户指定的字段名列表。

@JsonFilter("filter properties by name")  
class PropertyFilterMixIn {}  

class Bar  
{  
  public String id = "42";  
  public String name = "Fred";  
  public String color = "blue";  
  public Foo foo = new Foo();  
}  

class Foo  
{  
  public String id = "99";  
  public String size = "big";  
  public String height = "tall";  
}  

public class JacksonFoo  
{  
  public static void main(String[] args) throws Exception  
  {  
    ObjectMapper mapper = new ObjectMapper();  
    mapper.getSerializationConfig().addMixInAnnotations(  
        Object.class, PropertyFilterMixIn.class);  

    String[] ignorableFieldNames = { "id", "color" };  
    FilterProvider filters = new SimpleFilterProvider()  
      .addFilter("filter properties by name",   
          SimpleBeanPropertyFilter.serializeAllExcept(  
              ignorableFieldNames));  
    ObjectWriter writer = mapper.writer(filters);  

    System.out.println(writer.writeValueAsString(new Bar()));  
    // output:  
    // {"name":"James","foo":{"size":"big","height":"tall"}}  
  }  
} 

(Note: The relevant API may have changed slightly with a recent Jackson release.)

(注意:相关的API可能会随着杰克逊最近的发布而略有变化。)

While the example does use a seemingly unnecessary annotation, the annotation is not applied to the fields to be excluded. (To help get the API changed to simplify the necessary configuration a bit, please don't hesitate to vote for implementation of issue JACKSON-274.

虽然示例确实使用了看似不必要的注释,但注释并不应用于要排除的字段。(为了帮助修改API以简化必要的配置,请毫不犹豫地投票支持问题JACKSON-274的实现。

#2


10  

I wrote a library to deal with a similar use case. I needed to programmatically ignore fields based on the user requesting data. The normal Jackson options were just too heavy-handed, and I hated the way it made my code look.

我编写了一个库来处理类似的用例。我需要以编程方式忽略基于用户请求数据的字段。普通的杰克逊选项实在是太笨拙了,我讨厌它让我的代码看起来像这样。

The library makes this a whole lot easier to understand. It allows you to simply do this:

这个库使它更容易理解。它允许你简单地这样做:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.monitorjbl.json.JsonView;
import com.monitorjbl.json.JsonViewSerializer;
import static com.monitorjbl.json.Match.match;

//initialize jackson
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

 //get a list of the objects
List<MyObject> list = myObjectService.list();

String json;
if(user.getRole().equals('ADMIN')){
    json = mapper.writeValueAsString(list);
} else {
    json = mapper.writeValueAsString(JsonView.with(list)
        .onClass(MyObject.class, match()
           .exclude("*")
           .include("name")));
}

System.out.println(json);

The code is available on GitHub, hope it helps!

该代码在GitHub上是可用的,希望它能有所帮助!

#3


6  

Jackson relies on annotations for most things like this; but you do not have to directly annotate value classes. You can also use "mix-in annotations" (see http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html).

Jackson的大部分工作都依赖于注解;但是,您不必直接注释值类。您还可以使用“混合注释”(参见http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html)。

And then there are a few options you can use beyond basic @JsonIgnore (per-property) or @JsonIgnoreProperties (per-class), see http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

此外,除了基本的@JsonIgnore(每个属性)或@JsonIgnoreProperties(每个类)之外,还可以使用一些选项,参见http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

#4


5  

If you have filters defined on two or more pojo, you can try this:

如果您在两个或多个pojo上定义了过滤器,您可以尝试以下方法:

@JsonFilter("filterAClass") 
class AClass  
{       
  public String id = "42";  
  public String name = "Fred";  
  public String color = "blue";
  public int sal = 56;
  public BClass bclass = new BClass();  
}  

//@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@JsonFilter("filterBClass") 
class BClass  
{  

  public String id = "99";  
  public String size = "90";  
  public String height = "tall";  
  public String nulcheck =null;  
}  
public class MultipleFilterConcept {
    public static void main(String[] args) throws Exception  
      {   
        ObjectMapper mapper = new ObjectMapper();
     // Exclude Null Fields
        mapper.setSerializationInclusion(Inclusion.NON_NULL);
        String[] ignorableFieldNames = { "id", "color" };  
        String[] ignorableFieldNames1 = { "height","size" };  
        FilterProvider filters = new SimpleFilterProvider()  
          .addFilter("filterAClass",SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames))
          .addFilter("filterBClass", SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames1));  
        ObjectWriter writer = mapper.writer(filters);
       System.out.println(writer.writeValueAsString(new AClass())); 

      }
}

#5


2  

I wrote a library called Squiggly Filter, which selects fields based on a subset of the Facebook Graph API syntax. For example, to select the zipCode of the address field of the user object, you would use the query string ?fields=address{zipCode}. One of the advantages of Squiggly Filter is that as long as you have access to the ObjectMapper that renders the json, you do not to have to modify the code of any of your controller methods.

我编写了一个名为Squiggly Filter的库,它根据Facebook图形API语法的子集选择字段。例如,要选择user对象的address字段的zipCode,您将使用查询字符串?fields=address{zipCode}。Squiggly过滤器的优点之一是,只要您能够访问呈现json的ObjectMapper,就不需要修改任何控制器方法的代码。

Assuming, you are using the servlet API, you can do the following:

假设您正在使用servlet API,您可以执行以下操作:

1) Register a filter

1)注册一个过滤器

<filter> 
    <filter-name>squigglyFilter</filter-name>
    <filter-class>com.github.bohnman.squiggly.web.SquigglyRequestFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>squigglyFilter</filter-name>
    <url-pattern>/**</url-pattern> 
</filter-mapping>

2) Initialize the ObjectMapper

2)初始化objectmap

Squiggly.init(objectMapper, new RequestSquigglyContextProvider());

3) You can now filter your json

现在可以过滤json了

curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}

More information on Squiggly Filter is available on github.

在github上有更多关于Squiggly过滤器的信息。

#1


27  

The below example of excluding fields by name is from my blog post, Gson v Jackson - Part 4. (Search for the PropertyFilterMixIn.) This example demonstrates using a FilterProvider with a SimpleBeanPropertyFilter to serializeAllExcept a user-specified list of field names.

下面的例子是我的博客文章,Gson诉Jackson -第4部分。(寻找PropertyFilterMixIn。)这个示例演示了如何使用带有SimpleBeanPropertyFilter的FilterProvider来序列化一个用户指定的字段名列表。

@JsonFilter("filter properties by name")  
class PropertyFilterMixIn {}  

class Bar  
{  
  public String id = "42";  
  public String name = "Fred";  
  public String color = "blue";  
  public Foo foo = new Foo();  
}  

class Foo  
{  
  public String id = "99";  
  public String size = "big";  
  public String height = "tall";  
}  

public class JacksonFoo  
{  
  public static void main(String[] args) throws Exception  
  {  
    ObjectMapper mapper = new ObjectMapper();  
    mapper.getSerializationConfig().addMixInAnnotations(  
        Object.class, PropertyFilterMixIn.class);  

    String[] ignorableFieldNames = { "id", "color" };  
    FilterProvider filters = new SimpleFilterProvider()  
      .addFilter("filter properties by name",   
          SimpleBeanPropertyFilter.serializeAllExcept(  
              ignorableFieldNames));  
    ObjectWriter writer = mapper.writer(filters);  

    System.out.println(writer.writeValueAsString(new Bar()));  
    // output:  
    // {"name":"James","foo":{"size":"big","height":"tall"}}  
  }  
} 

(Note: The relevant API may have changed slightly with a recent Jackson release.)

(注意:相关的API可能会随着杰克逊最近的发布而略有变化。)

While the example does use a seemingly unnecessary annotation, the annotation is not applied to the fields to be excluded. (To help get the API changed to simplify the necessary configuration a bit, please don't hesitate to vote for implementation of issue JACKSON-274.

虽然示例确实使用了看似不必要的注释,但注释并不应用于要排除的字段。(为了帮助修改API以简化必要的配置,请毫不犹豫地投票支持问题JACKSON-274的实现。

#2


10  

I wrote a library to deal with a similar use case. I needed to programmatically ignore fields based on the user requesting data. The normal Jackson options were just too heavy-handed, and I hated the way it made my code look.

我编写了一个库来处理类似的用例。我需要以编程方式忽略基于用户请求数据的字段。普通的杰克逊选项实在是太笨拙了,我讨厌它让我的代码看起来像这样。

The library makes this a whole lot easier to understand. It allows you to simply do this:

这个库使它更容易理解。它允许你简单地这样做:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.monitorjbl.json.JsonView;
import com.monitorjbl.json.JsonViewSerializer;
import static com.monitorjbl.json.Match.match;

//initialize jackson
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

 //get a list of the objects
List<MyObject> list = myObjectService.list();

String json;
if(user.getRole().equals('ADMIN')){
    json = mapper.writeValueAsString(list);
} else {
    json = mapper.writeValueAsString(JsonView.with(list)
        .onClass(MyObject.class, match()
           .exclude("*")
           .include("name")));
}

System.out.println(json);

The code is available on GitHub, hope it helps!

该代码在GitHub上是可用的,希望它能有所帮助!

#3


6  

Jackson relies on annotations for most things like this; but you do not have to directly annotate value classes. You can also use "mix-in annotations" (see http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html).

Jackson的大部分工作都依赖于注解;但是,您不必直接注释值类。您还可以使用“混合注释”(参见http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html)。

And then there are a few options you can use beyond basic @JsonIgnore (per-property) or @JsonIgnoreProperties (per-class), see http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

此外,除了基本的@JsonIgnore(每个属性)或@JsonIgnoreProperties(每个类)之外,还可以使用一些选项,参见http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

#4


5  

If you have filters defined on two or more pojo, you can try this:

如果您在两个或多个pojo上定义了过滤器,您可以尝试以下方法:

@JsonFilter("filterAClass") 
class AClass  
{       
  public String id = "42";  
  public String name = "Fred";  
  public String color = "blue";
  public int sal = 56;
  public BClass bclass = new BClass();  
}  

//@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@JsonFilter("filterBClass") 
class BClass  
{  

  public String id = "99";  
  public String size = "90";  
  public String height = "tall";  
  public String nulcheck =null;  
}  
public class MultipleFilterConcept {
    public static void main(String[] args) throws Exception  
      {   
        ObjectMapper mapper = new ObjectMapper();
     // Exclude Null Fields
        mapper.setSerializationInclusion(Inclusion.NON_NULL);
        String[] ignorableFieldNames = { "id", "color" };  
        String[] ignorableFieldNames1 = { "height","size" };  
        FilterProvider filters = new SimpleFilterProvider()  
          .addFilter("filterAClass",SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames))
          .addFilter("filterBClass", SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames1));  
        ObjectWriter writer = mapper.writer(filters);
       System.out.println(writer.writeValueAsString(new AClass())); 

      }
}

#5


2  

I wrote a library called Squiggly Filter, which selects fields based on a subset of the Facebook Graph API syntax. For example, to select the zipCode of the address field of the user object, you would use the query string ?fields=address{zipCode}. One of the advantages of Squiggly Filter is that as long as you have access to the ObjectMapper that renders the json, you do not to have to modify the code of any of your controller methods.

我编写了一个名为Squiggly Filter的库,它根据Facebook图形API语法的子集选择字段。例如,要选择user对象的address字段的zipCode,您将使用查询字符串?fields=address{zipCode}。Squiggly过滤器的优点之一是,只要您能够访问呈现json的ObjectMapper,就不需要修改任何控制器方法的代码。

Assuming, you are using the servlet API, you can do the following:

假设您正在使用servlet API,您可以执行以下操作:

1) Register a filter

1)注册一个过滤器

<filter> 
    <filter-name>squigglyFilter</filter-name>
    <filter-class>com.github.bohnman.squiggly.web.SquigglyRequestFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>squigglyFilter</filter-name>
    <url-pattern>/**</url-pattern> 
</filter-mapping>

2) Initialize the ObjectMapper

2)初始化objectmap

Squiggly.init(objectMapper, new RequestSquigglyContextProvider());

3) You can now filter your json

现在可以过滤json了

curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}

More information on Squiggly Filter is available on github.

在github上有更多关于Squiggly过滤器的信息。