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

Jackson序列化:忽略空值及子对象全空的父类字段解决方案

解决方案:Jackson序列化时忽略空对象及空值,同时保留非空父对象

看起来你需要精准控制Jackson的JSON序列化行为:既要忽略空的子对象,又要在父对象有非空属性时保留父对象,还要在父类所有属性都为空时完全去掉父类字段。我来给你几个可行的方案:

方案一:局部字段自定义空对象过滤器(简单直接)

如果只是少数字段需要处理,推荐用Jackson的@JsonInclude(CUSTOM)结合自定义过滤器,判断对象是否所有属性为空,为空则忽略整个字段。

步骤1:创建空对象判断过滤器

public class EmptyObjectFilter {
    @Override
    public boolean equals(Object obj) {
        if (obj == null) return true;
        
        // 反射检查对象所有属性是否为null或空字符串
        try {
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                Object value = field.get(obj);
                
                if (value != null) {
                    // 字符串需额外判断非空
                    if (value instanceof String && !((String) value).isEmpty()) {
                        return false;
                    }
                    // 非字符串类型只要非null就视为有效
                    if (!(value instanceof String)) {
                        return false;
                    }
                }
            }
            // 所有属性都为空/空字符串,返回true表示忽略该字段
            return true;
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to check empty object", e);
        }
    }
}

步骤2:在目标字段上应用过滤器

修改你的类A,给需要判断的子对象字段加上自定义过滤器,同时保留全局的空值排除配置:

@JsonInclude(JsonInclude.Include.NON_EMPTY) // 全局排除空值、空集合、空字符串等
public class A {
    // 当B对象所有属性为空时,忽略这个字段
    @JsonProperty("classA.empName")
    @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = EmptyObjectFilter.class)
    public B empName = new B();

    @JsonProperty("classA.emp_name")
    public int age = 25;

    // 其他属性...
}

// 给B类也加上空值排除,确保B的空属性不被序列化
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class B {
    // B的属性,比如:
    public String name;
    public String department;
}

这样配置后:

  • 如果empName的B对象所有属性都是null/空字符串,classA.empName字段会被完全忽略;
  • 如果B有非空属性,该字段会正常序列化;
  • 类A的age属性(非空)会保留,确保父对象A被正常输出。

方案二:全局配置空对象忽略(适合大量类场景)

如果你有很多类需要处理空对象,可以通过自定义BeanSerializerModifier全局配置,避免每个字段都加注解。

步骤1:创建序列化器修改器

public class EmptyObjectSerializerModifier extends BeanSerializerModifier {
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (BeanPropertyWriter writer : beanProperties) {
            Class<?> propType = writer.getType().getRawClass();
            // 只处理自定义对象(排除基本类型、字符串、集合等)
            if (!propType.isPrimitive() && !String.class.isAssignableFrom(propType) && !Collection.class.isAssignableFrom(propType)) {
                writer.assignNullSerializer(new JsonSerializer<Object>() {
                    @Override
                    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                        boolean isEmpty = checkIfObjectIsEmpty(value);
                        if (!isEmpty) {
                            // 对象非空,正常序列化
                            gen.writeObject(value);
                        }
                        // 对象为空,不写入任何内容,即忽略该字段
                    }
                });
            }
        }
        return beanProperties;
    }

    private boolean checkIfObjectIsEmpty(Object obj) {
        if (obj == null) return true;
        try {
            for (Field field : obj.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                Object value = field.get(obj);
                if (value != null) {
                    if (value instanceof String && !((String) value).isEmpty()) {
                        return false;
                    }
                    if (!(value instanceof String)) {
                        return false;
                    }
                }
            }
            return true;
        } catch (IllegalAccessException e) {
            throw new IOException("Failed to check empty object", e);
        }
    }
}

步骤2:注册到ObjectMapper

在创建ObjectMapper时添加这个修改器,并设置全局空值排除:

ObjectMapper mapper = new ObjectMapper();
// 注册自定义修改器
mapper.setSerializerFactory(mapper.getSerializerFactory().withSerializerModifier(new EmptyObjectSerializerModifier()));
// 全局排除空值、空集合、空字符串
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

这样所有自定义对象类型的字段,只要对象所有属性为空,就会被自动忽略,无需在每个字段上加注解。

额外处理:排除基本类型默认值

如果你的需求还包括排除基本类型的默认值(比如int的0、boolean的false),可以把全局的NON_EMPTY换成NON_DEFAULT,或者在特定字段上单独加@JsonInclude(JsonInclude.Include.NON_DEFAULT)。

比如修改类A的age字段:

@JsonProperty("classA.emp_name")
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public int age = 25;

这样当age被设为0(int的默认值)时,该字段会被忽略;如果是25则正常保留。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:44:01