我正在尝试序列化Java POJO,如果不满足某些条件,则忽略某些字段。
到目前为止,我的解决方案如下:
public class PermissionSerializer extends StdSerializer<Object> implements ContextualSerializer {
private String role;
public PermissionSerializer() {
super(Object.class);
}
public PermissionSerializer(String role) {
super(Object.class);
this.role = role;
}
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
String curRole = SomeContext.getCurrentRole();
if (curRole.equals(role)) {
jgen.writeObject(value);
return;
}
jgen.writeNull();
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
String unit = null;
AllowedFor ann = null;
if (property != null) {
ann = property.getAnnotation(AllowedFor.class);
}
if (ann != null) {
unit = ann.role();
}
return new PermissionSerializer(unit);
}
}
然后在POJO中,我像这样使用它:
@JsonSerialize(using = PermissionSerializer.class)
@AllowedFor(role = "admin")
private String advancedField;
它实际上可行,除了它可能不是实现我想要的最好的方法。
但是,这种方法还有另一个问题。如果我们没有显示该字段的权限,即使我在类级别拥有null
,它也会在结果JSON中序列化为@JsonInclude(JsonInclude.Include.NON_NULL)
。
实际上可以完全忽略此字段吗?还是有更好的方法有条件地忽略字段?
答案 0 :(得分:2)
您可以编写一个ResponseAdvice来根据身份验证级别修饰响应。
首先,在您不希望显示的字段上,align*
,即使值是JsonIgnore
,也不想显示键。
null
现在,设置@JsonIgnore
private String advancedField;
。
ResponseAdvice
这就是您要做的几乎所有的事情。使用此方法的优点是,使用此方法可以将您绑定到@ControllerAdvice
public class MyResponseBodyAdvisor implements ResponseBodyAdvice<String> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return returnType.getDeclaringClass().equals(MyClass.class) && converterType.equals(MappingJackson2MessageConverter.class);
}
@Override
public String beforeBodyWrite(String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});
String currentRole = SomeContext.getCurrentRole();
if(currentRole.equals(Roles.SomeRole)) {
map.put("advancedField", "advancedValue");
}
return mapper.writeValueAsString(map);
}
}
生态系统,并且如果需要依赖注入等,可以使用它提供的所有优点。而且,它比在Spring
中使用验证逻辑更干净。如果您需要更好的用例支持,则应该考虑使用ResponseAdvice。
答案 1 :(得分:0)
您需要实现一个自定义过滤器,并将其添加到您的ObjectMapper实例中。假设您想做的事情不只是检查值是否为null,还可以做更复杂的事情,那么您可以创建一个自定义过滤器,该过滤器在要有条件序列化的属性的注释中使用类似表达式的内容。
我最近建立了类似的东西-https://github.com/johnhunsley/conditional-jackson-property-filter