Jackson中使用JsonInclude.NON_ABSENT如何保留null值忽略空/缺失值
解决Jackson保留显式null、忽略空值与缺失字段的方案
针对你的需求——仅忽略空白字符串("name": " ")和缺失的name字段,保留JSON中显式指定的null值,这里提供两种可行方案,其中方案2最为简洁:
方案1:自定义序列化器(灵活适配复杂场景)
通过自定义序列化器追踪字段是否被显式设置,同时过滤空白字符串:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class User { private String name; // 标记字段是否被显式设置(包括显式传null的情况) private boolean nameSet = false; @JsonSerialize(using = NameSerializer.class) public String getName() { return name; } @JsonSetter public void setName(String name) { this.name = name; this.nameSet = true; } public boolean isNameSet() { return nameSet; } // 自定义序列化逻辑 static class NameSerializer extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { User currentUser = (User) gen.getCurrentValue(); if (value == null) { // 仅当字段是显式设置的null时,才输出该字段 if (currentUser.isNameSet()) { gen.writeNull(); } } else if (value.isBlank()) { // 空白字符串直接忽略 } else { // 正常字符串正常输出 gen.writeString(value); } } } public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 测试缺失字段 System.out.println(mapper.writeValueAsString(mapper.readValue("{}", User.class))); // 输出{} // 测试显式null System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": null}", User.class))); // 输出{"name":null} // 测试空白字符串 System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": \" \"}", User.class))); // 输出{} // 测试正常字符串 System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": \"Xavior\"}", User.class))); // 输出{"name":"Xavior"} } }
方案2:利用NON_DEFAULT注解(简洁高效)
通过设置字段默认值为空白字符串,结合@JsonInclude(NON_DEFAULT)实现需求:
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; @JsonInclude(JsonInclude.Include.NON_DEFAULT) public class User { // 将字段默认值设为空白字符串,而非默认的null private String name = " "; public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 缺失字段:name保持默认空白字符串,NON_DEFAULT规则忽略该字段 System.out.println(mapper.writeValueAsString(mapper.readValue("{}", User.class))); // 输出{} // 显式null:name被设为null,不等于默认值,保留该字段 System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": null}", User.class))); // 输出{"name":null} // 空白字符串:name等于默认值,忽略该字段 System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": \" \"}", User.class))); // 输出{} // 正常字符串:name不等于默认值,保留该字段 System.out.println(mapper.writeValueAsString(mapper.readValue("{\"name\": \"Xavior\"}", User.class))); // 输出{"name":"Xavior"} } }
为什么@XmlElement(nillable = true)无效?
@XmlElement(nillable = true)是JAXB框架的注解,仅用于XML序列化时标记元素可为空,Jackson默认不识别该注解,且它对JSON序列化逻辑无任何影响。即便引入jackson-module-jaxb-annotations依赖让Jackson支持JAXB注解,也无法解决你的JSON序列化需求。
内容的提问来源于stack exchange,提问作者Akila Ranasinghe
相关产品推荐
相关产品推荐

