Java 使用Jackson 2的动态特性过滤器
我正在构建一个REST服务平台,其中我们必须支持以下查询模式:Java 使用Jackson 2的动态特性过滤器,java,json,jackson,Java,Json,Jackson,我正在构建一个REST服务平台,其中我们必须支持以下查询模式: format=summary这意味着我们必须仅反序列化使用自定义注释注释的POJO属性@summary format=detail这意味着我们必须仅反序列化使用自定义注释注释的POJO属性@detail fields=prop1、prop2、prop3,这意味着我们必须反序列化查询中提供的POJO属性 我正在使用Jackson 2(v2.3.0),我尝试了以下内容: 开发自定义注释(@Summary和@Detail) 开发了一个J
format=summary
这意味着我们必须仅反序列化使用自定义注释注释的POJO属性@summary
format=detail
这意味着我们必须仅反序列化使用自定义注释注释的POJO属性@detail
fields=prop1、prop2、prop3
,这意味着我们必须反序列化查询中提供的POJO属性- 开发自定义注释(
和@Summary
)@Detail
- 开发了一个JsonFilter(代码如下所示),并为我的POJO类注释了
@JsonFilter
公共类CustomFilter扩展了SimpleBeanPropertyFilter{
@凌驾
受保护的布尔值包括(BeanPropertyWriter propertyWriter){
if(logger.isDebugEnabled()){
debug(“include(BeanPropertyWriter)方法调用..”);
}
返回此值。反序列化(propertyWriter);
}
@凌驾
受保护的布尔值包括(PropertyWriter PropertyWriter){
if(logger.isDebugEnabled()){
debug(“include(PropertyWriter)方法调用..”);
}
返回此。反序列化((BeanPropertyWriter)propertyWriter);
}
私有布尔值反序列化(最终BeanPropertyWriter BeanPropertyWriter){
最终字符串格式=(字符串)AppContext.get(“格式”);
if(StringUtils.isNotBlank(格式)){
返回反序列化的注释(格式,beanPropertyWriter);
}否则{
@抑制警告(“未选中”)
final Set fieldNames=(Set)AppContext.get(“fieldNames”);
if(null!=fieldNames&!fieldNames.isEmpty()){
最终字符串serializedPropertyName=beanPropertyWriter.getSerializedName().getValue();
返回fieldNames.contains(serializedPropertyName);
}
}
返回false;
}
专用布尔值反序列化注释(最终字符串格式,最终BeanPropertyWriter BeanPropertyWriter){
if(StringUtils.equalsIgnoreCase(格式,“详细信息”)){
return(null!=beanPropertyWriter.getAnnotation(Detail.class));
}else if(StringUtils.equalsIgnoreCase(格式,“摘要”)){
return(null!=beanPropertyWriter.getAnnotation(Summary.class));
}
返回false;
}
}
我通过注释获得了预期的结果,但是我的第三个要求是支持属性名以进行筛选,这一要求不起作用
有人能帮忙吗;如果可能,请举例说明 如果您希望为每组字段使用自定义对象映射器,那么最好将创建的对象映射器保留在缓存中的某个位置,以便下次用户请求相同字段时可以重用对象映射器 您的缓存可以像一个
集那样简单,键是用户传入的字段。我编写了一个名为的库,它根据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>
3) 现在可以过滤json了
curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}
也可以基于注释选择字段
有关Squiggly筛选器的更多信息,请访问。我在StackOverflow中检查了一些帖子,但几乎所有人都建议编写自定义反序列化器/筛选器,并将其设置为ObjectMapper
,然后使用它。这意味着我必须为每个传入的请求创建一个新的ObjectMapper
实例,我想这不是一个好主意。我使用的是Spring,所以我创建了一次ObjectMapper
。所以,我必须找到一个解决方案,让我这样做。
public class CustomFilter extends SimpleBeanPropertyFilter {
@Override
protected boolean include(BeanPropertyWriter propertyWriter) {
if(logger.isDebugEnabled()) {
logger.debug("include(BeanPropertyWriter) method called..");
}
return this.deserialize(propertyWriter);
}
@Override
protected boolean include(PropertyWriter propertyWriter) {
if(logger.isDebugEnabled()) {
logger.debug("include(PropertyWriter) method called..");
}
return this.deserialize((BeanPropertyWriter) propertyWriter);
}
private boolean deserialize(final BeanPropertyWriter beanPropertyWriter) {
final String format = (String) AppContext.get("format");
if(StringUtils.isNotBlank(format)) {
return deserializeForAnnotation(format, beanPropertyWriter);
} else {
@SuppressWarnings("unchecked")
final Set<String> fieldNames = (Set<String>) AppContext.get("fieldNames");
if(null != fieldNames && !fieldNames.isEmpty()) {
final String serializedPropertyName = beanPropertyWriter.getSerializedName().getValue();
return fieldNames.contains(serializedPropertyName);
}
}
return false;
}
private boolean deserializeForAnnotation(final String format, final BeanPropertyWriter beanPropertyWriter) {
if(StringUtils.equalsIgnoreCase(format, "detail")) {
return (null != beanPropertyWriter.getAnnotation(Detail.class));
} else if(StringUtils.equalsIgnoreCase(format, "summary")) {
return (null != beanPropertyWriter.getAnnotation(Summary.class));
}
return false;
}
}
<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>
Squiggly.init(objectMapper, new RequestSquigglyContextProvider());
curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2}