[英]Spring filtering response fields with jackson
我正在尝试过滤嵌套 object 中的字段:
class Response {
// These objects themselves can have many fields within
private final PropA a;
private final PropB b;
@JsonCreator
public Response(PropA a, PropB b) { ... }
}
我想要一个通用的“过滤器助手”来实现上述逻辑。 这是我到目前为止所拥有的(遵循与这个项目类似的方法)
public class FilterHelper {
private final ObjectMapper objectMapper;
public FilterHelper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
this.objectMapper.addMixIn(Object.class, MyFilterMixin.class);
}
@JsonFilter("myfilter")
public static class MyFilterMixin {
}
private static class MyFilter extends SimpleBeanPropertyFilter {
private final Set<String> properties;
public MyFilter(Set<String> properties) {
super();
this.properties = properties;
}
@Override
public void serializeAsField(final Object pojo, final JsonGenerator jgen, final SerializerProvider provider,
final PropertyWriter writer) throws Exception {
System.out.println("************************** " + writer.getName());
if (properties.contains(writer.getName())) {
writer.serializeAsField(pojo, jgen, provider);
} else if (!jgen.canOmitFields()) {
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
}
public String filter(T obj, Set<String> fields) {
FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myfilter", new MyFilter(fields));
return objectMapper.writer(filterProvider).writeValueAsString(obj);
}
}
当我使用?fields=one,two
作为查询参数点击此端点时,我希望从打印到控制台的行中看到该顶级Response
object 中的每个字段,如下所示:
******************* a
******************* a1
******************* a2
******************* ..etc
******************* b
******************* b1
******************* b2
******************* ..etc
但我只看到 output 用于顶级a
和b
字段,然后在从端点获取 500 状态代码之前出现错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot resolve PropertyFilter with id 'myfilter'; no FilterProvider configured (through reference chain: com.google.common.collect.SingletonImmutableList[0])
值得一提的是,我以某种方式进行了这项工作,但是在进行了一些我不记得的更改后它被破坏了。
除非您需要为不同的字段提供自定义序列化,否则不应挂钩serializeAsField
,而应覆盖#include
变体方法:
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter#include(com.fasterxml.jackson.databind.ser.BeanPropertyWriter)
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter#include(com.fasterxml.jackson.databind.ser.PropertyWriter)
如下:
private static class MyFilter extends SimpleBeanPropertyFilter {
private final Set<String> properties;
public MyFilter(Set<String> properties) {
super();
this.properties = properties;
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return !this.properties.contains(writer.getName());
}
@Override
protected boolean include(PropertyWriter writer) {
return !this.properties.contains(writer.getName());
}
}
甚至还有一个com.fasterxml.jackson.databind.ser.PropertyFilter
工厂提供了一个过滤出一组特定字段的 com.fasterxml.jackson.databind.ser.PropertyFilter:
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter#serializeAllExcept(java.util.Set<java.lang.String>)
在过滤器助手级别,您将过滤后的 object 序列化为 JSON 然后将其反序列化(带有过滤字段)到您作为端点返回的 object
您可以简单地省略中间步骤,只需使用过滤器字段谓词对结果Response
进行消毒,并将结果 JSON 作为ResponseEntity
返回:
FilterHelper
:
@Component
public class FilterHelper {
private final ObjectMapper objectMapper;
@Autowired
public FilterHelper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
this.objectMapper.addMixIn(Object.class, MyFilterMixin.class);
}
@JsonFilter("myfilter")
public static class MyFilterMixin {
}
private static class MyFilter extends SimpleBeanPropertyFilter {
private final Set<String> properties;
public MyFilter(Set<String> properties) {
super();
this.properties = properties;
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return !this.properties.contains(writer.getName());
}
@Override
protected boolean include(PropertyWriter writer) {
return !this.properties.contains(writer.getName());
}
}
public String filter(Object dto, Set<String> fields) {
if (fields == null || fields.isEmpty()) {
return "";
}
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("myfilter", SimpleBeanPropertyFilter.serializeAllExcept(fields));
try {
return objectMapper.writer(filterProvider).writeValueAsString(dto);
} catch (JsonProcessingException e) {
return "";
}
}
}
Controller
:
@GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(OK)
ReponseEntity<String> someEndpoint(@RequestParam(name = "fields") Set<String> fields) {
Response response = getResponseFromSomewhere();
return ResponseEntity.ok(filterHelper.filter(response, fields));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.