java - jackson - 在序列化 HashMap 对象时跳过具有空值的键
问题描述
我正在尝试使用杰克逊对象映射器将带有 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));`
通过使用堆栈溢出问题中提供的答案。
我期待结果,{"expected":true}
但不知何故,带有null
值的键包含在结果中。
我该如何解决这个问题?
笔记:
- 代码在github 上。
- 我正在使用 jacksersion 版本 2.9.8
解决方案
当您放置@JsonInclude
一个字段时,这意味着如果该字段(不是字段的元素)为空,那么它将在转换中被忽略。
- 在您的情况下,当您使用
@JsonInclude
该additionalProperties
方法时,如果additionalProperties
(本身)为空,那么它将从转换中忽略。
所以
@JsonInclude
只检查additionalProperties
自己的空值,而不是它的元素。
示例:假设您有一个Ext
带有 的对象additionalProperties=null
,当您想要对其进行序列化时, 将additionalProperties
被忽略,因为它是null。
- 但是在您的场景中,地图的元素
additionalProperties
包含null并且杰克逊不会忽略它们。
解决方案 1
您可以序列化附加属性映射(本身)而不是整个 Ext 对象。
public static void main(String[] args) throws JsonProcessingException {
//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);
}
}
将 JSON 转换为 Ext 对象
您还可以Ext
从生成的字符串中获取对象。在这种情况下,您的对象具有过滤的附加属性(没有任何具有空键或空值的元素)
public static void main(String[] args) throws JsonProcessingException {
//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);
//Convert back JSON string to Ext object
Ext filterdExt = mapper.readValue(filterMap, Ext.class);
//Print AdditionalProperties of filterdExt ({"expected":true})
System.out.println(filterdExt.getAdditionalProperties());
}
解决方案 2
您可以编写自定义序列化程序。
此链接可能对此有用
推荐阅读
- vue.js - Vue - 从另一个站点加载外部组件
- java - Java:如果内部方法抛出错误,外部方法不应该也抛出错误吗?
- javascript - 使用python从javascript var数据创建字典
- kubernetes - Traefik 1.7 升级打破 kubernetes 1.7.12
- java - 循环内的 Android Studio 延迟
- javascript - 对用户隐藏 React Src 直到登录
- pandas - 如何在 Dask DataFrame 上正确执行多索引切片?
- jmeter - Jmeter - 同一线程组中不同http请求的计数变化
- kotlin - 如何调用具有接收器的类的函数?
- javascript - 如果索引为0,Vue.js如何添加活动类