You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:10:06