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

Java如何动态移除请求体中空或null的节点、数组

问题根因

@JsonInclude(value = JsonInclude.Include.NON_NULL)的生效规则是仅跳过值为null的字段,你当前场景里的空节点都不属于null值范畴:

  • country字段不是null,是一个所有属性均为null的空POJO实例,默认会序列化为{}
  • phoneNumbers、addresses字段本身不是null,是已经初始化的List集合,集合内存储的也是空POJO实例,默认会序列化为包含空对象的数组
    以上场景都不在NON_NULL的处理范围内,所以注解无法实现空节点移除效果。
通用无硬编码解决方案

通过Jackson全局配置+通用序列化规则实现自动过滤,不需要针对phoneNumbers、country这类固定字段写死排除逻辑,适配所有动态请求体场景:

1. 配置全局序列化包含规则

替换仅判断null的规则,在ObjectMapper层面统一配置非空判定标准,覆盖空字符串、空集合、空数组、空POJO场景:

ObjectMapper objectMapper = new ObjectMapper();
// 全局跳过null、空字符串、空集合、空数组、空Map值
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
// 补充配置:所有无有效属性的空POJO对象也跳过序列化
objectMapper.configOverride(Object.class)
        .setInclude(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, JsonInclude.Include.NON_EMPTY));

2. 处理集合/数组内嵌套空对象的场景

上述配置可以过滤本身为空的集合,但无法处理「集合长度不为0、但内部全是空POJO」的场景(比如你当前返回的"phoneNumbers": [{}]结构),需要注册通用序列化修改器,自动剔除集合内的空元素,过滤后集合为空则直接不输出对应节点:

objectMapper.registerModule(new SimpleModule() {
    @Override
    public void setupModule(SetupContext context) {
        context.addBeanSerializerModifier(new BeanSerializerModifier() {
            @Override
            public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
                beanProperties.forEach(propertyWriter -> {
                    Class<?> rawClass = propertyWriter.getType().getRawClass();
                    // 仅处理集合、数组类型属性,不影响其他字段逻辑
                    if (Collection.class.isAssignableFrom(rawClass) || propertyWriter.getType().isArrayType()) {
                        propertyWriter.assignSerializer(new JsonSerializer<Object>() {
                            @Override
                            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                                Collection<?> sourceCollection = value instanceof Collection
                                        ? (Collection<?>) value
                                        : Arrays.asList((Object[]) value);
                                // 过滤集合内所有无有效属性的空对象
                                List<Object> validElements = sourceCollection.stream()
                                        .filter(element -> !checkIsEmptyObject(element))
                                        .collect(Collectors.toList());
                                // 过滤后无有效元素的集合直接写null,交由全局NON_EMPTY规则跳过该节点
                                if (validElements.isEmpty()) {
                                    gen.writeNull();
                                    return;
                                }
                                // 输出有效元素组成的数组
                                gen.writeStartArray();
                                for (Object element : validElements) {
                                    gen.writeObject(element);
                                }
                                gen.writeEndArray();
                            }
                        });
                    }
                });
                return beanProperties;
            }
        });
    }

    // 通用空对象判定:对象序列化后无任何属性即为空对象
    private boolean checkIsEmptyObject(Object obj) {
        if (obj == null) return true;
        JsonNode jsonNode = objectMapper.valueToTree(obj);
        return jsonNode.isObject() && jsonNode.size() == 0;
    }
});

效果说明

配置完成后,所有序列化逻辑自动执行:

  • 自动跳过null值、空字符串、空集合、空数组、空POJO对象
  • 自动剔除集合/数组内的空对象元素,剔除后集合为空则不输出对应节点
  • 完全不需要硬编码指定待排除的字段名,适配任意动态增减字段的POST请求场景
  • 序列化输出结果和你期望的结构完全一致,仅保留携带有效值的节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:36:18