[英]jersey/jackson - filter properties based on query parameter
Filtering out properties with Jackson is pretty simple: 使用Jackson过滤属性非常简单:
final FilterProvider filters = new SimpleFilterProvider().
addFilter(... the name of the filter ...,
SimpleBeanPropertyFilter.filterOutAllExcept(... enumeration of properties ...));
<object mapper>.writer(filters).writeValueAsString(... the bean ...);
I am trying to integrate this in my Jersey REST application. 我想在我的Jersey REST应用程序中集成它。 The API user has the possibility to filter the properties by providing a query string:
API用户可以通过提供查询字符串来过滤属性:
https://the-api/persons?fields=name,age,location,gender
What is the most elegant way to do this in Jersey? 泽西岛最优雅的方式是什么? I could easily execute the above in my resource methods, but this somehow kills the elegance of Jersey.
我可以轻松地在我的资源方法中执行上述操作,但这会以某种方式杀死Jersey的优雅。 Also, I believe that creating a new ObjectMapper for every request will have performance penalties.
此外,我相信为每个请求创建一个新的ObjectMapper会有性能损失。
I could write a MessageBodyWriter
which fetches the fields
query parameter from the UriInfo
context and serializes the entity to json while applying a filter based on the fields
query parameter. 我可以编写一个
MessageBodyWriter
,它从UriInfo
上下文中获取fields
查询参数,并在应用基于fields
查询参数的过滤器时将实体序列化为json。 Is this the best way to do this? 这是最好的方法吗? Like this:
像这样:
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JustTesting implements MessageBodyWriter<Object> {
@Context
UriInfo uriInfo;
@Context
JacksonJsonProvider jsonProvider;
public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return MediaType.APPLICATION_JSON_TYPE.equals(mediaType);
}
public long getSize(Object object, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return -1;
}
public void writeTo(Object object, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap, OutputStream outputStream) throws IOException, WebApplicationException {
final FilterProvider filters = new SimpleFilterProvider().addFilter("MyFilter", SimpleBeanPropertyFilter.filterOutAllExcept(uriInfo.getQueryParameters().getFirst("fields")));
jsonProvider.locateMapper(aClass, mediaType).writer(filters).writeValue(outputStream, object);
}
}
It seems to work, but I am unsure if it is smart to do it like this. 它似乎有用,但我不确定这样做是否聪明。 I am new to the Jersey library.
我是泽西岛图书馆的新手。
My current solution to a similar problem is to register the following servlet filter: 我目前解决类似问题的方法是注册以下servlet过滤器:
@Singleton
public class ViewFilter implements Filter {
private @Inject Provider<ViewBeanPropertyFilter> filter;
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void destroy() { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ObjectWriterInjector.set(new ObjectWriterModifier() {
@Override
public ObjectWriter modify(EndpointConfigBase<?> endpoint, MultivaluedMap<String, Object> responseHeaders, Object valueToWrite, ObjectWriter w, JsonGenerator g) throws IOException {
return w.with(new FilterProvider() {
@Override
public BeanPropertyFilter findFilter(Object filterId) {
if(filterId.equals(ViewFilterJacksonModule.FILTER_NAME)) {
return filter.get();
}
return null;
}
});
}
});
chain.doFilter(request, response);
}
public static class ViewBeanPropertyFilter extends SimpleBeanPropertyFilter {
private @Inject ViewManager manager;
@Override
protected boolean include(BeanPropertyWriter writer) {
Class<?> cls = writer.getMember().getDeclaringClass();
return manager.isFieldInView(cls, writer.getMember().getName());
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
}
}
It's a little more gnarly than the solution you provided, but leaves the standard JacksonJsonProvider
serialization in place. 它比您提供的解决方案更加粗糙,但
JacksonJsonProvider
了标准的JacksonJsonProvider
序列化。
It can be improved by pulling the (possibly) existing FilterProvider
via m.getConfig().getFilterProvider()
and delegating to it before / after your filter. 可以通过
m.getConfig().getFilterProvider()
拉动(可能)现有的FilterProvider
并在过滤器之前/之后委托给它来改进它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.