
本文详解为何 @JsonInclude(JsonInclude.Include.NON_ABSENT) 在 Lombok @Value 类中失效,并提供兼容 Jackson 与 Lombok 的可靠配置方案,确保 null 字段(如 payingInformation)完全不输出。
本文详解为何 `@jsoninclude(jsoninclude.include.non_absent)` 在 lombok `@value` 类中失效,并提供兼容 jackson 与 lombok 的可靠配置方案,确保 `null` 字段(如 `payinginformation`)完全不输出。
在使用 Jackson 进行 JSON 序列化时,开发者常期望通过 @JsonInclude(JsonInclude.Include.NON_ABSENT) 自动跳过值为 null 的字段。但如问题所示,即使显式标注该策略,payingInformation: null 仍出现在最终 JSON 中——根本原因在于 Lombok 的 @Value 注解与 Jackson 的序列化机制存在冲突。
@Value 是一个不可变类生成器:它将所有字段设为 final,仅生成 getter 和 toString()/equals()/hashCode(),不生成 setter,也不提供无参构造函数。而 Jackson 默认依赖以下任一机制来识别“缺席”(absent)状态:
- 使用
Optional<t></t>包装字段(此时Optional.empty()才被识别为ABSENT); - 或通过
@JsonCreator+ 全参数构造器配合@JsonProperty显式声明可选参数; - 或依赖标准 JavaBean 的 setter + 无参构造器进行属性赋值后判断。
NON_ABSENT 并非等价于 NON_NULL:它只跳过逻辑上“未设置”(absent)的值(如 Optional.empty()、未传入 @JsonCreator 参数的字段),而对普通 null 引用字段不做任何过滤。因此,payingInformation = null 被视为“存在但值为 null”,而非“缺席”,自然不会被排除。
✅ 正确解决方案是 放弃 @Value,改用 @Data + 显式构造控制:
// 替换 @Value 为 @Data,并补充必要注解
@Data
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL) // ✅ 更直观且符合需求
public class PayingInformationPart {
Boolean isPaying;
Date payingDateTime;
}
同理更新其他类:
@Data
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ProductPart {
@NonNull Long productId;
@NonNull Integer offerId;
@Builder.Default
ActivationPeriodPart activationPeriod = ActivationPeriodPart.builder().build();
@Singular List<valuepart> values;
@Builder.Default
Date orderDateTime = new Date(1529897304000L);
PayingInformationPart payingInformation; // null 将被自动忽略
}
@Data
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ProductsMessageBody implements Message {
@NonNull Integer clientId;
@NonNull Long subsId;
@Singular List<productpart> products;
}</productpart></valuepart>
? 关键说明:
-
@Data自动生成 getter/setter/无参构造器/全参构造器(含@NonNull校验),满足 Jackson 反序列化与序列化基础要求; -
@NoArgsConstructor确保 Jackson 可实例化对象(尤其在反序列化或测试中); -
@JsonInclude(JsonInclude.Include.NON_NULL)直接语义明确:所有null值字段均不参与序列化,完美解决payingInformation: null问题; - 若未来需支持
Optional语义(如区分“未提供” vs “明确设为 null”),则应改用Optional<payinginformationpart></payinginformationpart>并保留NON_ABSENT,但需同步调整构造逻辑与业务含义。
⚠️ 注意事项:
- 避免混用
@Value与 Jackson 的@JsonInclude(NON_ABSENT)—— 二者设计目标不匹配; -
@Builder本身不影响序列化行为,但@Builder.Default初始化的非null字段(如activationPeriod)会正常输出,符合预期; - 如需全局配置(而非逐类标注),可在
ObjectMapper中统一设置:objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
综上,NON_NULL 是处理常规 null 字段过滤的首选策略;NON_ABSENT 仅适用于 Optional、@JsonCreator 参数缺失等真正“缺席”场景。合理选择注解组合,才能让 Jackson 序列化既简洁又可控。










