我需要在渲染之前按名称排除某些字段。字段列表是动态的,因此我无法使用注释。
我尝试创建自定义序列化程序,但我无法在那里获得字段名称。
在GSON中,我使用过ExclusionStrategy
,但杰克逊没有这样的功能。有没有等价的?
答案 0 :(得分:29)
以下按名称排除字段的示例来自my blog post, Gson v Jackson - Part 4。 (搜索PropertyFilterMixIn
。)此示例演示如何使用FilterProvider
使用SimpleBeanPropertyFilter
到serializeAllExcept
用户指定的字段名称列表。
@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"}}
}
}
(注意:最近杰克逊发布的相关API可能略有变化。)
虽然示例确实使用了看似不必要的注释,但注释不会应用于要排除的字段。 (为了帮助改变API以简化必要的配置,请毫不犹豫地投票支持问题JACKSON-274的实施。
答案 1 :(得分:10)
我写了一个库来处理类似的用例。我需要以编程方式忽略基于请求数据的用户的字段。正常的杰克逊选择太过苛刻,我讨厌它使我的代码看起来的方式。
图书馆让这一切变得更容易理解。它允许您简单地执行此操作:
public class TapeDeck
{
// code
}
public class TapeDeckTestDrive
{
public static void main(String [] args)
{
TapeDeck t = new TapeDeck();
t.canRecord = true;
t.playTape();
if(t.canRecord == true)
{
t.recordTape();
}
}
}
代码可用on GitHub,希望有帮助!
答案 2 :(得分:6)
杰克逊依赖注释来解决大多数事情;但您不必直接注释值类。您还可以使用“混合注释”(请参阅http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html)。
然后除了基本的@JsonIgnore
(每个属性)或@JsonIgnoreProperties
(每个级别)之外,您还可以使用一些选项,请参阅http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
答案 3 :(得分:6)
如果您在两个或更多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()));
}
}
答案 4 :(得分:4)
我写了一个名为Squiggly Filter的库,它根据Facebook Graph API语法的一个子集选择字段。例如,要选择用户对象的地址字段的zipCode,您将使用查询字符串?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)初始化ObjectMapper
Squiggly.init(objectMapper, new RequestSquigglyContextProvider());
3)您现在可以过滤您的json
curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}
有关Squiggly过滤器的更多信息,请参见github。