Jackson-仅当满足条件时才序列化一个值,忽略null

时间:2019-01-27 20:43:35

标签: java jackson json-deserialization

我正在尝试序列化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)

实际上可以完全忽略此字段吗?还是有更好的方法有条件地忽略字段?

2 个答案:

答案 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