41

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

我尝试创建自定义序列化程序,但我无法在那里获取字段名称。

在 GSON 中我使用过ExclusionStrategy,但杰克逊没有这样的功能。有没有等价物?

4

5 回答 5

42

以下按名称排除字段的示例来自我的博客文章 Gson v Jackson - Part 4。(搜索PropertyFilterMixIn。)此示例演示了使用FilterProvideraSimpleBeanPropertyFilterserializeAllExcept用户指定的字段名称列表。

@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"}}  
  }  
} 

(注意:随着最近的 Jackson 版本,相关 API 可能略有变化。)

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

于 2012-12-09T22:47:10.373 回答
14

我写了一个库来处理类似的用例。我需要根据用户请求数据以编程方式忽略字段。普通的 Jackson 选项过于笨拙,我讨厌它使我的代码看起来的方式。

该库使这更容易理解。它允许您简单地执行此操作:

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

代码在 GitHub 上,希望对你有帮助!

于 2015-06-20T20:31:11.490 回答
10

如果你在两个或多个 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())); 

      }
}
于 2014-09-29T06:52:01.083 回答
6

Jackson 对大多数此类事情都依赖注释;但您不必直接注释值类。您还可以使用“混合注释”(参见http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html)。

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

于 2012-12-10T20:40:27.990 回答
4

我编写了一个名为Squiggly Filter的库,它根据 Facebook Graph API 语法的子集选择字段。例如,要选择用户对象的地址字段的邮政编码,您可以使用查询字符串?fields=address{zipCode}。Squiggly Filter 的优点之一是,只要您可以访问呈现 json 的 ObjectMapper,您就不必修改任何控制器方法的代码。

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

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)初始化对象映射器

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

3)您现在可以过滤您的json

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

有关 Squiggly 过滤器的更多信息,请访问github

于 2016-10-17T01:20:46.633 回答