猿问

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

如果不满足某些条件,我正在尝试序列化 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)在类级别上也是如此。


是否有可能完全忽略这个领域?或者也许有更好的方法有条件地忽略字段?


守着星空守着你
浏览 236回答 2
2回答

炎炎设计

您可以编写一个ResponseAdvice来根据身份验证级别装饰响应。首先JsonIgnore在您不想显示的字段上,即使值为null.@JsonIgnoreprivate String advancedField;现在,设置ResponseAdvice.@ControllerAdvicepublic class MyResponseBodyAdvisor implements ResponseBodyAdvice<String> {&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {&nbsp; &nbsp; &nbsp; &nbsp; return returnType.getDeclaringClass().equals(MyClass.class) && converterType.equals(MappingJackson2MessageConverter.class);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String beforeBodyWrite(String body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});&nbsp; &nbsp; &nbsp; &nbsp; String currentRole = SomeContext.getCurrentRole();&nbsp; &nbsp; &nbsp; &nbsp; if(currentRole.equals(Roles.SomeRole)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;map.put("advancedField", "advancedValue");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return mapper.writeValueAsString(map);&nbsp; &nbsp; }}这就是你所要做的。使用这种方法的优点是,您可以通过这种方法绑定到Spring生态系统,并且可以使用它提供的所有好处,如果您需要依赖注入等等。此外,它比在Serializer. 如果您需要对您的用例提供更好的支持,您应该查看ResponseAdvice 。

拉丁的传说

您需要实现一个自定义过滤器并将其添加到您的 ObjectMapper 实例中。假设您想要做更复杂的事情,而不仅仅是检查一个值是否为空,那么您可以创建一个自定义过滤器,该过滤器在您想要有条件地序列化的属性的注释中使用类似于表达式的东西。我最近建立了类似的东西 -&nbsp;https://github.com/johnhunsley/conditional-jackson-property-filter
随时随地看视频慕课网APP

相关分类

Java
我要回答