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

如何强制Jackson对Null和缺失属性使用@JsonCreator反序列化?

解决Jackson枚举反序列化时Null/缺失字段不调用@JsonCreator的问题

问题场景

使用包含枚举字段的Java Record类进行JSON反序列化时,出现如下不符合预期的情况:

  • 当枚举字段值为null时,Jackson不会调用枚举类的@JsonCreator方法,直接将字段赋值为null
  • 当枚举字段缺失时,同样直接赋值为null

需要让null值和缺失字段都通过@JsonCreator方法处理,得到预设的默认枚举值(如示例中的RED)。

模型类代码

record MyRec(
  String first,
  Color second
){}

// ---

enum Color{
  RED, GREEN;

  @JsonCreator
  static Color fromName(String name){
    if (name == null || "red".equals(name)){
      return RED; 
    } else if ("green".equals(name)) {
      return GREEN;
    } else {
      throw new IllegalArgumentException(name);
    }
  }
}

反序列化结果对比

JSON内容实际结果预期结果状态
{"first": "hi", "second": "red"}MyRec("hi", RED)MyRec("hi", RED)正常
{"first": "hi", "second": null}MyRec("hi", null)MyRec("hi", RED)异常
{"first": "hi"}MyRec("hi", null)MyRec("hi", RED)异常

解决方案

方案1:修改Record构造逻辑处理Null值

利用Java Record的紧凑构造器,在构造实例时主动处理null的枚举字段,直接调用枚举的fromName方法生成默认值:

record MyRec(String first, Color second) {
    // 紧凑构造器:自动处理所有构造参数
    public MyRec {
        if (second == null) {
            // 调用@JsonCreator方法处理null情况
            second = Color.fromName(null);
        }
    }
}

原理:不管JSON中枚举字段是null还是缺失,Jackson都会将该字段初始化为null传入构造器,此时在构造器中统一调用fromName(null)即可得到预期的RED值。

方案2:自定义枚举反序列化器

通过自定义反序列化器接管Color类型的所有反序列化逻辑,包括null值和缺失字段的处理:

步骤1:编写自定义反序列化器

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;

public class ColorDeserializer extends StdDeserializer<Color> {
    public ColorDeserializer() {
        super(Color.class);
    }

    @Override
    public Color deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String value = parser.getText();
        // 直接复用枚举的fromName方法处理所有情况(包括null)
        return Color.fromName(value);
    }
}

步骤2:给枚举类绑定反序列化器

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = ColorDeserializer.class)
enum Color{
  RED, GREEN;

  @JsonCreator
  static Color fromName(String name){
    if (name == null || "red".equals(name)){
      return RED; 
    } else if ("green".equals(name)) {
      return GREEN;
    } else {
      throw new IllegalArgumentException(name);
    }
  }
}

步骤3:处理缺失字段

为了让缺失字段也触发反序列化逻辑,需要给Record的second字段设置默认值,通过添加额外的构造器实现:

record MyRec(String first, Color second) {
    // 当second字段缺失时,调用此构造器生成默认值
    public MyRec(String first) {
        this(first, Color.fromName(null));
    }
}

原理:自定义反序列化器会处理所有传入的Color类型值(包括null),而额外的构造器则确保字段缺失时主动生成预期的默认枚举值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:31:08