为了账号安全,请及时绑定邮箱和手机立即绑定

Jackson - 仅在满足条件时序列化值,忽略空值

Jackson - 仅在满足条件时序列化值,忽略空值

守着星空守着你 2022-05-25 10:23:07
如果不满足某些条件,我正在尝试序列化 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 回答

?
炎炎设计

TA贡献1808条经验 获得超4个赞

您可以编写一个ResponseAdvice来根据身份验证级别装饰响应。


首先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生态系统,并且可以使用它提供的所有好处,如果您需要依赖注入等等。此外,它比在Serializer. 如果您需要对您的用例提供更好的支持,您应该查看ResponseAdvice 。


查看完整回答
反对 回复 2022-05-25
?
拉丁的传说

TA贡献1789条经验 获得超8个赞

您需要实现一个自定义过滤器并将其添加到您的 ObjectMapper 实例中。假设您想要做更复杂的事情,而不仅仅是检查一个值是否为空,那么您可以创建一个自定义过滤器,该过滤器在您想要有条件地序列化的属性的注释中使用类似于表达式的东西。

我最近建立了类似的东西 - https://github.com/johnhunsley/conditional-jackson-property-filter


查看完整回答
反对 回复 2022-05-25
  • 2 回答
  • 0 关注
  • 235 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信