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

Spring中Jackson的JsonNode字段如何简洁设置默认值?

更简洁的实现方案

针对你遇到的问题,我有几个更优雅的解决方案,既能避免重复代码,又能满足info为null时getInfo().toString()返回"{}"的需求:

方案1:全局Jackson反序列化配置(推荐,无侵入)

如果你的场景主要是JSON反序列化时处理null值,推荐使用自定义Jackson反序列化器,全局生效,不需要修改任何DTO的代码:

  1. 首先创建一个自定义反序列化器,将null的JsonNode替换为空的ObjectNode:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import java.io.IOException;

public class NullToEmptyObjectNodeDeserializer extends JsonDeserializer<JsonNode> {
    @Override
    public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.readValueAsTree();
        return node == null ? JsonNodeFactory.instance.objectNode() : node;
    }
}
  1. 在Spring Boot中注册这个反序列化器到ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        // 为JsonNode类型注册自定义反序列化器
        module.addDeserializer(JsonNode.class, new NullToEmptyObjectNodeDeserializer());
        objectMapper.registerModule(module);
        return objectMapper;
    }
}

这样所有JsonNode类型的字段在反序列化时,如果原JSON中没有该字段或者值为null,都会被自动设置为空的ObjectNode,后续调用getInfo().toString()自然返回"{}"。如果需要覆盖手动设置null的场景,可以配合下面的方案2补充处理。

方案2:通用工具方法+Lombok简化

如果你需要覆盖手动设置null的场景,可以提取一个通用工具方法,结合Lombok避免重复编写setter/getter:

  1. 创建工具类:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;

public class JsonNodeUtils {
    public static JsonNode emptyIfNull(JsonNode node) {
        return node == null ? JsonNodeFactory.instance.objectNode() : node;
    }
}
  1. 在DTO中使用自定义setter/getter(Lombok会识别自定义方法,不会生成默认实现):
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;

@Data
class ABC {
    @JsonProperty("info")
    private JsonNode info;

    // 自定义setter,自动处理null值
    public void setInfo(JsonNode info) {
        this.info = JsonNodeUtils.emptyIfNull(info);
    }

    // 双重保险:即使字段被直接赋值null,getter也返回空节点
    public JsonNode getInfo() {
        return JsonNodeUtils.emptyIfNull(this.info);
    }
}

这样不管是反序列化、手动调用setter,还是直接给字段赋值null,getInfo()都会返回空的ObjectNode,完全满足需求。工具类的方法可以在多个DTO中复用,无需重复编写判断逻辑。

方案3:抽象父类复用逻辑

如果有多个DTO都包含类似的JsonNode字段,可以创建一个抽象父类,把getter/setter的逻辑抽离进去,子类直接继承即可:

import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;

public abstract class BaseJsonNodeDto {
    protected JsonNode info;

    @JsonSetter("info")
    public void setInfo(JsonNode info) {
        this.info = info == null ? JsonNodeFactory.instance.objectNode() : info;
    }

    public JsonNode getInfo() {
        return this.info;
    }

    // 可以添加更多类似JsonNode字段的通用处理逻辑
}

然后你的DTO继承这个父类:

import lombok.Data;

@Data
class ABC extends BaseJsonNodeDto {
    // 其他字段...
}

这种方式适合多个DTO有相同字段的场景,彻底消除重复代码。

补充说明

你提到的@JsonProperty(defaultValue = "{}")无效是正常的——这个注解的defaultValue属性仅用于生成API文档(比如Swagger),不会实际为字段设置默认值,所以无法解决你的问题。

内容的提问来源于stack exchange,提问作者comiventor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:38:21