
本文详解 Jackson 中 @JsonInclude 对自定义类(如 Mgmt)的“空值”判定失效问题,通过 CUSTOM 模式配合自定义过滤器,实现仅当内部集合为空时彻底排除该字段(而非输出 "mgmt": {})。
本文详解 jackson 中 `@jsoninclude` 对自定义类(如 `mgmt`)的“空值”判定失效问题,通过 `custom` 模式配合自定义过滤器,实现仅当内部集合为空时彻底排除该字段(而非输出 `"mgmt": {}`)。
Jackson 的 @JsonInclude(JsonInclude.Include.NON_EMPTY) 是常用且便捷的序列化过滤注解,但它对“空”的判定有明确边界:仅原生支持 Collection、Map、String、数组等标准类型——不自动递归检查自定义 POJO 的内部状态。因此,即使 Mgmt 类中 values 为 new ArrayList(),Jackson 仍会将其视为“非空对象”,最终序列化为 "mgmt": {},违背业务预期。
要真正实现“当 Mgmt.values 为空列表时,完全省略 mgmt 字段”,必须启用 JsonInclude.Include.CUSTOM 模式,并提供一个语义明确的过滤器类。
✅ 正确实现方式:自定义 valueFilter
首先,定义一个过滤器类(需继承 Object 并重写 equals 方法),其返回 true 表示“该实例应被排除”:
public class MgmtEmptyFilter {
@Override
public boolean equals(Object obj) {
// 若非 Mgmt 实例,不参与过滤(避免误判 null 或其他类型)
if (!(obj instanceof Mgmt)) {
return false;
}
Mgmt mgmt = (Mgmt) obj;
// 仅当 values 为 null 或 isEmpty() 时,才排除该 mgmt 实例
return mgmt.values == null || mgmt.values.isEmpty();
}
}⚠️ 注意:原始答案中 return true 用于非 Mgmt 实例是错误逻辑(会导致所有非 Mgmt 值被过滤),此处已修正为 return false,确保类型安全;核心判断聚焦于 mgmt.values 状态。
然后,在目标字段上使用 @JsonInclude 指定 CUSTOM 模式与该过滤器:
class Test {
@JsonInclude(
value = JsonInclude.Include.CUSTOM,
valueFilter = MgmtEmptyFilter.class
)
Mgmt mgmt;
}? 序列化效果验证
假设有以下实例:
Test test1 = new Test();
test1.mgmt = new Mgmt(); // values = null → 被排除 → 输出: {}
Test test2 = new Test();
test2.mgmt = new Mgmt();
test2.mgmt.values = Collections.emptyList(); // values.isEmpty() → 被排除 → 输出: {}
Test test3 = new Test();
test3.mgmt = new Mgmt();
test3.mgmt.values = Arrays.asList("a", "b"); // 非空 → 保留 → 输出: {"mgmt":{"values":["a","b"]}}? 关键注意事项
- 过滤器类必须是无参构造、线程安全的普通类,Jackson 会通过反射实例化它;
- equals() 方法中务必先做 instanceof 类型检查,避免 ClassCastException;
- valueFilter 仅作用于字段值本身(即 Mgmt 实例),不适用于嵌套属性;若需更复杂逻辑(如多字段联合判定),可在 equals() 中扩展;
- 若 Mgmt 类已重写 equals(),请确保其语义与“序列化空值判定”一致,否则建议仍使用独立的 valueFilter 类以解耦关注点。
通过这一模式,你将完全掌控 Jackson 对任意自定义类型的序列化可见性,让 JSON 输出严格符合领域语义——既简洁,又精准。










