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

如何在Jakarta Validation中验证集合为空?是否存在@Empty注解?

问题描述

我需要验证以下两个集合属性为空:

// should be empty!
@JsonbTransient
@JsonIgnore
@XmlAnyAttribute
private Map<QName, Object> unknownAttributes;

// should be empty!
@JsonbTransient
@JsonIgnore
@XmlAnyElement
private List<Element> unknownElements;

我了解@NotEmpty注解可用于反向验证,目前通过以下方式实现验证:

@AssertTrue(message = "unknown attributes should be empty")
private boolean isUnknownAttributesEmpty() {
    if (unknownAttributes == null) {
        return true;
    }
    return unknownAttributes.isEmpty();
}

@AssertTrue(message = "unknown elements should be empty")
private boolean isUnknownElementsEmpty() {
    if (unknownElements == null) {
        return true;
    }
    return unknownElements.isEmpty();
}

请问是否有更优的实现方式?为何Jakarta Validation中没有@Empty注解,还是说该注解实际存在?


解答

一、更优实现方式

有两种更简洁的方案可以替代当前的@AssertTrue写法:

方案1:利用现有@Size注解(无需自定义)

如果你使用Hibernate Validator(Jakarta Validation的主流实现),可以直接用@Size(max = 0)来实现需求:

@Size(max = 0, message = "unknown attributes should be empty")
@JsonbTransient
@JsonIgnore
@XmlAnyAttribute
private Map<QName, Object> unknownAttributes;

@Size(max = 0, message = "unknown elements should be empty")
@JsonbTransient
@JsonIgnore
@XmlAnyElement
private List<Element> unknownElements;

@Size(max=0)会校验集合/映射的元素数量不超过0,也就是必须为空,同时null会被判定为有效(和你当前的校验逻辑完全一致),这种方式无需额外代码,最简洁。

方案2:自定义通用@Empty注解(高复用性)

如果需要更语义化的注解,或者项目中有多处类似校验,可以自定义一个@Empty注解:

1. 定义注解类

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EmptyValidator.class)
@Documented
public @interface Empty {
    String message() default "集合或映射必须为空";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

2. 实现校验器

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Collection;
import java.util.Map;

public class EmptyValidator implements ConstraintValidator<Empty, Object> {
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }
        if (value instanceof Collection) {
            return ((Collection<?>) value).isEmpty();
        }
        if (value instanceof Map) {
            return ((Map<?, ?>) value).isEmpty();
        }
        // 非集合/映射类型默认通过校验,也可根据需求抛出异常
        return true;
    }
}

3. 直接在属性上使用

@Empty(message = "unknown attributes should be empty")
@JsonbTransient
@JsonIgnore
@XmlAnyAttribute
private Map<QName, Object> unknownAttributes;

@Empty(message = "unknown elements should be empty")
@JsonbTransient
@JsonIgnore
@XmlAnyElement
private List<Element> unknownElements;

这种方式的优势是语义清晰,后续其他属性需要校验为空时直接复用注解即可。

二、Jakarta Validation中没有内置@Empty注解的原因

Jakarta Validation的内置注解聚焦于高频通用的校验场景,比如@NotEmpty(非空)、@NotNull(非null)、@Size(范围校验)等。而"必须为空"属于相对小众的校验需求,因此官方规范中并未定义@Empty注解,主流实现(如Hibernate Validator)也没有额外提供这个内置注解。

不过通过上面提到的两种方案,完全可以轻松实现对应的校验逻辑。


内容的提问来源于stack exchange,提问作者Jin Kwon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 07:23:13