在 Spring Data rest json Response 中动态过滤实体字段
Posted
技术标签:
【中文标题】在 Spring Data rest json Response 中动态过滤实体字段【英文标题】:Filtering entity fields dynamically in Spring Data rest json Response 【发布时间】:2015-10-15 00:22:28 【问题描述】:嗨,我需要动态忽略 spring 数据休息响应中的实体字段 [我知道它们可以通过使用 @JsonIgnore 注释以静态方式完成] 理想情况下基于 spring 安全角色。角色部分仍然是可管理的,但如何动态忽略 json 响应中的字段是一个挑战。 经过一些分析和文档,我认为 jackson 是要走的路,因为 spring data rest 确实通过 jackson 模块和 mixins http://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.custom-jackson-deserialization 提供了 jackson 定制。
所以我认为在 jackson api 中可以通过 @jsonFilter 完成,然后在 ObjectMapper 写入对象时提供相同的内容 [更多详细信息在这里 http://www.cowtowncoder.com/blog/archives/2011/09/entry_461.html] 。
但我不确定这如何与 Spring data rest 连接(基本上是我可以将 filterprovider 注入 spring data rest objectmapper 的部分)。让我知道是否有人尝试过这个或 Spring 数据团队的某人有见解。
如果我能达到同样的效果,我会自己发布答案。
更新
所以我发现实现自定义过滤的方法是通过 jackson BeanSerializerModifier。得到了 Twitter 上 @cowtowncoder 的大力帮助。还有有用的参考或使用 jackson 过滤的圣杯http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
【问题讨论】:
ok 终于可以实现了,很快就会给出答案 【参考方案1】:所以是的,最后我能够解决这个问题。这里的诀窍是使用自定义 BeanSerializerModifier 并通过自定义模块注册它[这是可用于自定义 spring data rest jackson 序列化的自定义钩子],类似于
setSerializerModifier( new CustomSerializerModifier()).build()));
现在您可以通过覆盖方法 changeProperties 来自定义我们的 BeanSerializerModifier 以应用您的自定义过滤器,该过滤器基本上包括和排除 BeanPropertyWriter 根据您的逻辑。示例如下
List<BeanPropertyWriter> included = Lists.newArrayList();
for (BeanPropertyWriter property : beanProperties)
if (!filter.contains(property.getName()))
included.add(property);
通过这种方式,您可以在每个类中包含任何逻辑或以其他方式包含任何逻辑,并以自定义方式过滤属性表单响应。希望对您有所帮助
还更新了我在 github 上的代码,请查看https://github.com/gauravbrills/SpringPlayground
【讨论】:
【参考方案2】:这个例子展示了如何在 Spring Boot REST 控制器中实现动态 JSON 转换(过滤)。它使用 AOP 控制器建议在运行时更改控制器方法输出。 github上的代码:https://github.com/andreygrigoriev/jsonfilter
AOP 建议
@ControllerAdvice
@SuppressWarnings("unused")
public class FilterAdvice implements ResponseBodyAdvice<Object>
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response)
String fields = ((ServletServerHttpRequest) request).getServletRequest().getParameter("fields");
return new FilterMappingJacksonValue<>(body, StringUtils.isEmpty(fields) ? new String[] : fields.split(","));
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType)
return true;
FilterMappingJacksonValue
public class FilterMappingJacksonValue<T> extends MappingJacksonValue
public FilterMappingJacksonValue(final T value, final String... filters)
super(value);
setFilters(new SimpleFilterProvider().addFilter("dynamicFilter",
filters.length > 0 ? SimpleBeanPropertyFilter.filterOutAllExcept(filters) : SimpleBeanPropertyFilter.serializeAll()));
简单的 DTO
@Data
@AllArgsConstructor
@JsonFilter("dynamicFilter")
public class Book
String name;
String author;
图书控制器
@RestController
@SuppressWarnings("unused")
public class BookController
@GetMapping("/books")
public List<Book> books()
List<Book> books = new ArrayList<>();
books.add(new Book("Don Quixote", "Miguel de Cervantes"));
books.add(new Book("One Hundred Years of Solitude", "Gabriel Garcia Marquez"));
return books;
【讨论】:
以上是关于在 Spring Data rest json Response 中动态过滤实体字段的主要内容,如果未能解决你的问题,请参考以下文章
spring-data-rest 集成测试因简单的 json 请求而失败
在 Spring Data rest json Response 中动态过滤实体字段
纯 JSON(非 HAL 格式)的 Spring Data REST
Spring data rest @ManyToOne 字段不在 json 中