我需要根据请求中提供的参数过滤响应实体属性。
举个例子:
GET http://example.org/api/entity/1
会回复
{ "id": 1234, "foo": "FOO", "bar": "BAR" }
如果请求包含参数include=id,foo
,我只想包含参数标识的属性:
{ "id": 1234, "foo": "FOO" }
通常,使用杰克逊过滤器可以使用documented few中的places进行此类动态过滤。我无法理解的是为FilterProvider
提供对HttpServletRequest
(或类似的任何作用域)的引用的方法。
ObjectMapper mapper = ...
mapper.setFilters(new FilterProvider() {
public BeanPropertyFilter findFilter(Object filterId) {
// FIXME: filter out all except those in HttpServletRequest#getParameter("include")
return SimpleBeanPropertyFilter.filterOutAllExcept(Collections.<String>emptySet());
}
});
如果我添加servlet或Jersey过滤器来配置ObjectWriterInjector
,则可以使用potential solution和example。我希望有一个更清晰,更直接的方法。
这一切都发生在Dropwizard应用程序中,如果这恰好有任何区别。
答案 0 :(得分:0)
让我先从免责声明开始,从未与DropWizard
合作,所以我可能会在这里瞎扯一下。但你可以这样做:
@GET
@Path("test")
public String get(@QueryParam("include") List<String> includeList) throws JsonProcessingException {
MyClass myClass = new MyClass("aaa");
ObjectMapper mapper = ...;
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept(new HashSet<>(includeList)));
mapper.setFilters(filterProvider);
return mapper.writeValueAsString(myClass);
}
请求将在:
GET http://example.org/api/entity/1
您当然可以在问题中保留请求并添加:
@GET
@Path("test")
public String get2(@QueryParam("include") String includeList) throws JsonProcessingException {
MyClass myClass = new MyClass("testing123");
String[] arr = includeList.split(",");
ObjectMapper mapper = ...;
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept(new HashSet<>(Arrays.asList(arr))));
mapper.setFilters(filterProvider);
return mapper.writeValueAsString(myClass);
}
此解决方案的问题是返回String而不是对象本身会使测试更难。
答案 1 :(得分:0)
好的,请抓住你的帽子:这有点牵扯。 :)
Jackson 2.3为JAX-RS提供程序添加了通用扩展,允许对用于读写JSON(和其他格式)的ObjectReader
和ObjectWriter
进行深度自定义。
增加是通过这个问题:
https://github.com/FasterXML/jackson-jaxrs-providers/issues/33
但要点是,您可以在处理请求期间注册ObjectReaderInjector
和/或ObjectWriterInjector
:通常这是通过doFilter()
javax.servlet.Filter
方法完成的,在DropWizard调用Jackson读取请求之前,写回复。
然后在读/写之前调用注入器(如果有注册的话),让代码进行任何想要的更改。
使用ObjectReader
和ObjectWriter
的实例代替ObjectMapper
,因为它们完全是线程安全的;您无法安全地重新配置ObjectMapper
,但读取器/编写器实例可以使用各种“withXxx()”调用进行重新配置(只需记住它们创建新实例并且不要修改实例方法!)。
通过以上问题举例:
https://github.com/FasterXML/jackson-jaxrs-providers/commit/ddf256f6aaaf1d669c1c4323c5359cc20cf40654
显示了它们如何联系在一起。 代码并不像人们希望的那么简单,但它是通用的,非常强大的方式来定制阅读请求的所有方面,写出响应。
答案 2 :(得分:0)
您可以从 MyApplication 类的 run 方法中的环境参数中获取对象映射器:
public class MyApplication extends Application<MyApplicationConfiguration> {
@Override
public void run(MyApplicationConfiguration configuration, Environment environment) throws Exception {
environment.getObjectMapper().setFilterProvider(new FilterProvider() {
public BeanPropertyFilter findFilter(Object filterId) {
//filter code here
}
});
}
}