Jackson ObjectMapper - 从远程响应反序列化后,如何在值为 false 时排除字段?

Jackson ObjectMapper - How to exclude field when value is false after de-serialized from remote response?

我正在远程调用外部服务 A,它将 return 响应作为 json,然后使用对象映射器反序列化为 MyResponse 对象。在那之后,在我当前的服务中,我需要附加这个对象并输出到 UI.

来自服务 A 的 MyResponse 中的一个字段是布尔值,我只希望我的 UI 响应在值为真时包含此字段。 请注意,我无权修改我的 MyResponse 对象,因为它是只读的。所以我创建了一个 MixIn class 也尝试了几种方法但是没有用..

    public class MyResponse {

        private String stringValue;
        private int intValue;
        // Expectation: only include this field when value true, and exclude it when value is false
        private boolean booleanValue;
    }

    // @JsonIgnoreProperties(value = { "booleanValue" })
    // @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
    private static class MixInMyResponse {

    }

    // this would be my rest service eventually send myResponse to UI
    public MyResponse readFromRemote() throws IOException {
        String jsonAsString =
            "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":false}";
        ObjectMapper mapper = new ObjectMapper();
        // configure object mapper with mix in
        mapper.getDeserializationConfig().addMixInAnnotations(MyResponse.class, MixInMyResponse.class);
        MyResponse myResponse = mapper.readValue(jsonAsString, MyResponse.class);
        // Expectation: writeValue needs only include booleanValue when value true, and exclude booleanValue when value is false
        String writeValue = mapper.writeValueAsString(myResponse);
        System.out.println(writeValue);
        return myResponse;
    }

  1. 使用 @JsonIgnoreProperties(value = { "booleanValue" }):当值为 false 时这会起作用,但当值为 true 时它也不包括该字段
  2. 使用 @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY):当值是 false 时,这会将字段 booleanValue 反序列化为 false,所以我的 returned myResponse/writeValue 仍然会有这个字段到 UI.

对此还有什么建议吗?

编写您自己的序列化程序

public class MyResponseSerializer extends JsonSerializer<MyResponse> {
    @Override
    public void serialize(MyResponse myResponse, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("stringValue", myResponse.getStringValue());
        jsonGenerator.writeNumberField("intValue", myResponse.getIntValue());
        if (myResponse.isBooleanValue()) {
            jsonGenerator.writeBooleanField("booleanValue", myResponse.isBooleanValue());
        }
        jsonGenerator.writeEndObject();
    }
}

用 ObjectMapper 注册它

@Test
public void test3() throws IOException {
    MyResponse response1 = new MyResponse("response1", 1, true);
    MyResponse response2 = new MyResponse("response2", 1, false);

    ObjectMapper objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addSerializer(MyResponse.class, new MyResponseSerializer());
    objectMapper.registerModule(module);
    System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(response1));
    System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(response2));
}

看到这个tutorial

当我看到您无法修改 MyResponse 以添加注释时,我编辑了原始答案。

你当然可以这样做。

首先,您的 booleanValue 字段应该是盒装类型 Boolean 而不是预设类型 boolean。因为原始类型 boolean 默认值为 false.

您可以为 booleanValue 创建一个 setter 方法并用 @JsonProperty("booleanValue") 注释它,如下所示。

public class MyResponse {
    private String stringValue;
    private int intValue;
    private Boolean booleanValue;

    @JsonProperty("booleanValue")
    public void anyNameYouWant(Boolean b) {
        if(b) this.booleanValue = true;
    }
    
    // getters and setters
}

终于可以进行以下操作了,

String s = "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":false}";
ObjectMapper om = new ObjectMapper();
om.readValue(s, MyResponse.class);