我正在构建一个REST服务平台,我们必须支持以下查询模式:
format=summary
这意味着我们只需反序列化使用自定义注释注释的POJO属性@Summary
format=detail
这意味着我们只需反序列化使用自定义注释注释的POJO属性@Detail
fields=prop1,prop2,prop3
表示我们必须反序列化查询中提供的POJO属性。我正在使用Jackson 2(v2.3.0)我尝试了以下内容:
@Summary
和@Detail
)@JsonFilter
。的 Location.java 的
@JsonFilter("customFilter")
public class Location implements Serializable {
@Summary
@Detail
private String id;
@Summary
@Detail
private String name;
@Summary
@Detail
private Address address;
// ... getters n setters
的 Address.java 的
@JsonFilter("customFilter")
public class Address implements Serializable {
@Detail
private String addressLine1;
@Detail
private String addressLine2;
@Detail
private String addressLine3;
@Detail
@Summary
private String city;
@Summary
@Detail
private String postalCode;
// ... getters n setters
的 CustomFilter.java 的
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;
}
}
我正在使用注释获得预期结果,但我支持要过滤的属性名称的第3个要求不起作用。
有人可以提供帮助;如果可能的话用一些例子?
答案 0 :(得分:3)
我写了一个名为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。
答案 1 :(得分:0)
如果您想要为每组字段设置自定义对象映射器,那么最好的办法是将创建的对象映射器保留在某个缓存中,以便下次用户请求相同的字段时对象mapper可以重复使用。
您的缓存可以像Set<String,ObjectMapper>
一样简单,密钥是用户传入的字段。