jackson-序列化HashMap对象时跳过具有空值的键

问题描述 投票:0回答:2

我正在尝试使用杰克逊对象映射器将带有hashmap的Java对象序列化为json字符串。

下面是Ext的类定义-

        import com.fasterxml.jackson.annotation.JsonAnyGetter;
        import com.fasterxml.jackson.annotation.JsonAnySetter;
        import com.fasterxml.jackson.annotation.JsonIgnore;
        import com.fasterxml.jackson.annotation.JsonInclude;
        import com.fasterxml.jackson.annotation.JsonPropertyOrder;
        import com.fasterxml.jackson.annotation.JsonInclude.Include;
        import java.io.Serializable;
        import java.util.HashMap;
        import java.util.Map;
        import java.util.Objects;

        @JsonInclude(Include.NON_NULL)
        @JsonPropertyOrder({})
        public class Ext implements Serializable {

            @JsonIgnore
            private Map<String, Object> additionalProperties = new HashMap();
            private static final long serialVersionUID = -4500317258794294335L;

            public Ext() {
            }

            @JsonAnyGetter
            public Map<String, Object> getAdditionalProperties() {
                return this.additionalProperties;
            }

            @JsonAnySetter
            public void setAdditionalProperty(String name, Object value) {
                this.additionalProperties.put(name, value);
            }

            // ignore toString, equals and hascode

            public static class ExtBuilder {
                protected Ext instance;

                public ExtBuilder() {
                    if (this.getClass().equals(Ext.ExtBuilder.class)) {
                        this.instance = new Ext();
                    }
                }

                public Ext build() {
                    Ext result = this.instance;
                    this.instance = null;
                    return result;
                }

                public Ext.ExtBuilder withAdditionalProperty(String name, Object value) {
                    this.instance.getAdditionalProperties().put(name, value);
                    return this;
                }
            }
        }

下面是示例测试用例-

    @Test
    public void testNullObjectSerialization() throws Exception {

        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
        mapper.setDefaultPropertyInclusion(
              JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL));

        ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
        mapper.writeValue(out, new Ext.ExtBuilder().withAdditionalProperty("unexpected", null).withAdditionalProperty("expected", true).build());
        String result = new String(out.toByteArray());
        Assert.assertEquals("{\"expected\":true}", result);
    }

我用过

mapper.setDefaultPropertyInclusion(
              JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL));` 

通过使用堆栈溢出question中提供的答案。

我期望结果为{"expected":true},但结果中包含具有null值的键。

如何解决此问题?

注意:Cod eis位于github here

java jackson jackson2
2个回答
0
投票

WriteValue不会以任何方式考虑包含:它仅适用于JSON的编写。转换是先写后读的顺序;但是在完成读取时,输出不再包含排除的值。

替换此代码:

ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
        mapper.writeValue(out, new Ext.ExtBuilder().withAdditionalProperty("unexpected", null).withAdditionalProperty("expected", true).build());
        String result = new String(out.toByteArray());
        Assert.assertEquals("{\"expected\":true}", result);

作者

ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
            mapper.writeValue(out, mapper.convertValue(new Ext.ExtBuilder().withAdditionalProperty("unexpected", null).withAdditionalProperty("expected", true).build(), Ext.class));

            String result = new String(out.toByteArray());
            Assert.assertEquals("{\"expected\":true}", result);

0
投票

[当您将@JsonInclude放在字段上或在映射器中使用(setSerializationInclusion)时,这意味着如果该字段(不是字段的元素)null,则它将被忽略转换。

  • 在您的情况下,当您在@JsonInclude上使用additionalProperties时,这意味着,如果additionalPropertiesitself)为null,则将从转换中将其忽略。

所以@JsonInclude仅检查additionalProperties本身而不检查其元素。


示例:假设您有一个带有ExtadditionalProperties=null对象,当您要对其进行序列化时,additionalProperties被忽略,因为它是null

但是在您的情况下,additionalProperties映射的elements包含null,Jackson不会忽略它们。

您可以序列化其他属性映射(本身),而不是整个Ext对象。

    //Create Ext  Object
    Ext ext = new Ext.ExtBuilder().withAdditionalProperty("unexpected", null).withAdditionalProperty("expected", true).build();

    //Config
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

    //Conversion the additionalProperties map (ext.getAdditionalProperties())
    String filterMap = mapper.writeValueAsString(ext.getAdditionalProperties());

    //Result ({"expected":true})
    System.out.println(filterMap);

而且您还可以从生成的字符串中获取Ext对象。在这种情况下,您的对象具有已过滤的AdditionalProperties(不包含具有null键或null值的任何元素)

//Convert JSON string to Ext object
Ext filterdExt = mapper.readValue(filterMap, Ext.class);

//Print the map of filterdExt 
System.out.println(filterdExt.getAdditionalProperties());
© www.soinside.com 2019 - 2024. All rights reserved.