【问题标题】:jackson filter properties without annotations没有注释的杰克逊过滤器属性
【发布时间】:2012-06-06 14:37:15
【问题描述】:
public Class User {
private String name;
private Integer age;
...
}
ObjectMapper om = new ObjectMapper();
om.writeValueAsString(user);
如何在不使用 @JsonIgnore 之类的任何注释的情况下过滤属性?
【问题讨论】:
标签:
java
json
annotations
jackson
【解决方案2】:
按名称排除属性示例:
public Class User {
private String name = "abc";
private Integer age = 1;
//getters
}
@JsonFilter("dynamicFilter")
public class DynamicMixIn {
}
User user = new User();
String[] propertiesToExclude = {"age"};
ObjectMapper mapper = new ObjectMapper()
.addMixIn(Object.class, DynamicMixIn.class);
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("dynamicFilter", SimpleBeanPropertyFilter.serializeAllExcept(propertiesToExclude));
mapper.setFilterProvider(filterProvider);
mapper.writeValueAsString(user); // {"name":"abc"}
您可以代替DynamicMixIn 创建MixInByPropName
@JsonIgnoreProperties(value = {"age"})
public class MixInByPropName {
}
ObjectMapper mapper = new ObjectMapper()
.addMixIn(Object.class, MixInByPropName.class);
mapper.writeValueAsString(user); // {"name":"abc"}
注意:如果您只想排除 User 的属性,您可以将方法 addMixIn 的参数 Object.class 更改为 User.class
按类型排除属性,您可以创建MixInByType
@JsonIgnoreType
public class MixInByType {
}
ObjectMapper mapper = new ObjectMapper()
.addMixIn(Integer.class, MixInByType.class);
mapper.writeValueAsString(user); // {"name":"abc"}
【解决方案3】:
有点慢,但我使用两阶段复制。首先使用spring BeanUtils,其次使用Jackson。
public static void copyWithIgnore(final Object source, final Object target, final String... ignoreProperties) {
try {
final ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final Object ignoredSource;
if (ObjectUtils.isEmpty(ignoreProperties)) {
ignoredSource = source;
} else {
ignoredSource = source.getClass().getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(source, ignoredSource, ignoreProperties);
}
mapper.readerForUpdating(target).readValue(mapper.writeValueAsString(ignoredSource));
} catch (Exception e) {
throw new RuntimeException("Cannot deserialize and instantiate source class");
}
}
【解决方案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) 初始化 ObjectMapper
Squiggly.init(objectMapper, new RequestSquigglyContextProvider());
3) 您现在可以过滤您的 json
curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}
有关 Squiggly 过滤器的更多信息,请访问 github。