如何为Spring REST Docs编写自定义类型验证器?
在Spring REST Docs中编写自定义字段类型验证器
嗨,我来帮你搞定自定义类型验证器的事儿!Spring REST Docs默认的JsonFieldType验证已经能覆盖基础类型,但如果需要更定制化的校验(比如UUID、邮箱、自定义格式字符串),咱们可以通过实现自定义的FieldValidator接口来搞定,下面一步步来:
1. 核心思路:实现FieldValidator接口
Spring REST Docs的字段校验逻辑都封装在FieldValidator接口里,咱们只需要实现这个接口的validate方法,在里面编写自己的校验规则——如果字段值不符合要求,抛出PayloadHandlingException就能让测试失败,和内置验证的行为保持一致。
2. 示例1:自定义UUID类型验证器
比如你要验证某个字段必须是合法的UUID,先写一个验证器类:
import org.springframework.restdocs.payload.FieldValidator; import org.springframework.restdocs.payload.PayloadHandlingException; import java.util.UUID; public class UuidFieldValidator implements FieldValidator { @Override public void validate(String fieldPath, Object fieldValue) throws PayloadHandlingException { // 处理null值:如果字段是可选的,这里可以直接返回;如果必填,就抛出异常 if (fieldValue == null) { throw new PayloadHandlingException( String.format("Field at path '%s' cannot be null", fieldPath) ); } try { // 尝试把值转成UUID,失败则抛出异常 UUID.fromString(fieldValue.toString()); } catch (IllegalArgumentException e) { throw new PayloadHandlingException( String.format("Field at path '%s' is not a valid UUID. Actual value: %s", fieldPath, fieldValue) ); } } }
3. 在文档配置中使用自定义验证器
接下来在你的responseFields配置里,把这个验证器绑定到对应的字段上就行,替换或者补充原来的.type()配置:
.andDo(document("one-valid-connection", pathParameters( parameterWithName("ip").description("The requested IPv4 address.") ), responseFields( fieldWithPath("username") .type(JsonFieldType.STRING) .description("The username associated with the connection."), // 使用自定义UUID验证器 fieldWithPath("sessionId") .validator(new UuidFieldValidator()) .description("The unique UUID identifier for the session.") ) ))
4. 示例2:扩展内置类型验证(比如邮箱格式)
如果你想在基础类型(比如STRING)的基础上增加额外校验(比如邮箱格式),可以继承内置的JsonFieldTypeValidator,先做基础类型验证,再叠加自定义规则:
import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.restdocs.payload.JsonFieldTypeValidator; import org.springframework.restdocs.payload.PayloadHandlingException; public class EmailFieldValidator extends JsonFieldTypeValidator { public EmailFieldValidator() { // 先指定基础类型为STRING super(JsonFieldType.STRING); } @Override public void validate(String fieldPath, Object fieldValue) throws PayloadHandlingException { // 先执行父类的STRING类型验证(确保值是字符串类型) super.validate(fieldPath, fieldValue); // 再做邮箱格式校验 if (fieldValue != null) { String email = fieldValue.toString(); // 简单的邮箱正则,你可以换成更严谨的 String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; if (!email.matches(emailRegex)) { throw new PayloadHandlingException( String.format("Field at path '%s' is not a valid email. Actual value: %s", fieldPath, email) ); } } } }
使用的时候直接绑定到字段:
fieldWithPath("userEmail") .validator(new EmailFieldValidator()) .description("The user's valid email address.")
小提示
- 如果字段是可选的(允许返回null),记得在验证器里处理null值,避免不必要的异常;
- 验证器抛出的
PayloadHandlingException会直接导致测试失败,和内置验证的逻辑完全一致; - 你也可以把常用的自定义验证器封装成静态工具类,方便复用。
内容的提问来源于stack exchange,提问作者jaw
相关产品推荐
相关产品推荐

