Jackson JSON序列化:当嵌套对象所有字段为空时如何忽略?
嘿,这个问题我之前也碰到过!你现在的情况是,虽然给Person加了@JsonInclude(NON_EMPTY),但因为Child和Sibling是提前new出来的(不是null),Jackson默认只会把null或者空集合/空字符串这类视为“空”,不会主动判断嵌套对象的所有字段是不是都为空。下面给你几个靠谱的解决办法:
方案一:关闭空对象报错 + 给嵌套类加JsonInclude(简单省心)
这个方法适合大多数简单场景,步骤很清晰:
- 先关闭Jackson的空对象序列化报错特性——默认情况下,如果一个对象没有可序列化的非空字段,Jackson会抛出
JsonMappingException,所以得先把这个限制关掉:
ObjectMapper mapper = new ObjectMapper(); // 关闭空对象序列化时的报错 mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
- 给你的
Child和Sibling类也加上@JsonInclude(JsonInclude.Include.NON_EMPTY)(如果只需要忽略null字段,也可以用NON_NULL):
@JsonInclude(JsonInclude.Include.NON_EMPTY) public class Child { // 你的字段、getter和setter } @JsonInclude(JsonInclude.Include.NON_EMPTY) public class Sibling { // 你的字段、getter和setter }
这样一来,当Child的所有字段都是null或空值时,Jackson会把这个Child对象视为“空”,序列化Person时就会自动忽略这个字段。
方案二:自定义空对象过滤器(通用灵活)
如果你的嵌套类比较多,或者需要更复杂的空值判断逻辑(比如要排除空集合、空数组),用自定义过滤器更合适。Jackson 2.9+支持@JsonInclude(Include.CUSTOM),可以指定一个过滤器来判断对象是否应该被忽略:
- 先写一个过滤器类,用来检查对象的所有字段是否都为空:
import com.fasterxml.jackson.databind.ser.ValueFilter; import java.lang.reflect.Field; public class EmptyObjectFilter implements ValueFilter { @Override public Object filter(Object value, JsonGenerator gen, SerializerProvider serializers) { if (value == null) { return null; } try { // 遍历对象的所有字段,检查是否有非空值 for (Field field : value.getClass().getDeclaredFields()) { field.setAccessible(true); Object fieldValue = field.get(value); if (fieldValue != null) { // 如果是字符串,额外排除空串情况 if (!(fieldValue instanceof String) || !((String) fieldValue).trim().isEmpty()) { // 只要有一个字段非空,就保留原对象 return value; } } } // 所有字段都是null或空串,返回null让Jackson忽略这个字段 return null; } catch (IllegalAccessException e) { throw new RuntimeException("检查空对象失败", e); } } }
- 然后在
Person类的嵌套字段上加上这个过滤器注解:
@JsonInclude(JsonInclude.Include.NON_EMPTY) public class Person { String name; @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = EmptyObjectFilter.class) Child child = new Child(); @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = EmptyObjectFilter.class) Sibling sibling = new Sibling(); // 你的getter和setter }
这个方法的好处是不用修改每个嵌套类,只要在需要判断的字段上加注解就行,判断逻辑也可以根据需求随时调整。
方案三:在getter里手动判断(适合简单场景)
如果你的嵌套类字段很少,也可以直接在Person的getter方法里做判断,当嵌套对象所有字段都为空时返回null,结合@JsonInclude(NON_NULL)就能忽略:
@JsonInclude(JsonInclude.Include.NON_NULL) public class Person { String name; Child child = new Child(); Sibling sibling = new Sibling(); // 假设Child有name和age两个字段 public Child getChild() { if ((child.getName() == null || child.getName().trim().isEmpty()) && child.getAge() == null) { return null; } return child; } // 同理给Sibling的getter加判断逻辑 // 其他getter和setter }
这种方法最直接,但缺点是每个嵌套类都要写对应的判断逻辑,要是字段多或者嵌套类多的话会比较繁琐。
内容的提问来源于stack exchange,提问作者David DeMar
相关产品推荐
相关产品推荐

