java - @Valid 在使用没有控制器的杰克逊创建对象时
问题描述
当从前端发送请求时,我在控制器中使用 @Valid 验证了一个模型:
@NotNull
@Size(min=1, message="Name should be at least 1 character.")
private String name;
@NotNull
@Pattern(regexp = "^https://github.com/.+/.+$", message = "Link to github should match https://github.com/USER/REPOSITORY")
private String github;
但现在我也在用杰克逊的 ObjectMapper 创建一个没有控制器的对象。有没有办法在 ObjectMapper 中注册此验证,或者我应该只检查设置器中的变量?
解决方案
您可以在反序列化后扩展BeanDeserializer
和验证对象。要注册此 bean,请使用SimpleModule
.
带有验证的简单 bean 反序列化器:
class BeanValidationDeserializer extends BeanDeserializer {
private final static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
private final Validator validator = factory.getValidator();
public BeanValidationDeserializer(BeanDeserializerBase src) {
super(src);
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Object instance = super.deserialize(p, ctxt);
validate(instance);
return instance;
}
private void validate(Object instance) {
Set<ConstraintViolation<Object>> violations = validator.validate(instance);
if (violations.size() > 0) {
StringBuilder msg = new StringBuilder();
msg.append("JSON object is not valid. Reasons (").append(violations.size()).append("): ");
for (ConstraintViolation<Object> violation : violations) {
msg.append(violation.getMessage()).append(", ");
}
throw new ConstraintViolationException(msg.toString(), violations);
}
}
}
我们可以如下使用它:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.File;
import java.io.IOException;
import java.util.Set;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
SimpleModule validationModule = new SimpleModule();
validationModule.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (deserializer instanceof BeanDeserializer) {
return new BeanValidationDeserializer((BeanDeserializer) deserializer);
}
return deserializer;
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(validationModule);
System.out.println(mapper.readValue(jsonFile, Pojo.class));
}
}
class Pojo {
@NotNull
@Size(min = 1, message = "Name should be at least 1 character.")
private String name;
@NotNull
@Pattern(regexp = "^https://github.com/.+/.+$", message = "Link to github should match https://github.com/USER/REPOSITORY")
private String github;
// getters, setters, toString()
}
对于有效JSON
载荷:
{
"name": "Jackson",
"github": "https://github.com/FasterXML/jackson-databind"
}
印刷:
Pojo{name='Jackson', github='https://github.com/FasterXML/jackson-databind'}
对于无效JSON
负载:
{
"name": "",
"github": "https://git-hub.com/FasterXML/jackson-databind"
}
印刷:
Exception in thread "main" javax.validation.ConstraintViolationException: JSON object is not valid. Reasons (2): Name should be at least 1 character., Link to github should match https://github.com/USER/REPOSITORY,
at BeanValidationDeserializer.validate(JsonApp.java:110)
at BeanValidationDeserializer.deserialize(JsonApp.java:97)
也可以看看:
推荐阅读
- node.js - NodeJS 流媒体视频
- assembly - 汇编 CALL 和 RET 堆栈
- angular - 使用 Jest 模拟 Angular 组件的 @Input 值
- r - 折叠R中不同子字符串的空格
- python - 有什么方法可以在 Python 3.8 中获取“_cffi_backend”模块
- javascript - 未捕获的 TypeError:无效的解构不可迭代实例的尝试
- amazon-web-services - 列出 OEC 中特定项目的 EC2 实例的私有 IP 地址
- crlf-vulnerability - Npm 漏洞问题未修复?
- php - 为什么我在更改页面时删除了我在 url 中的过滤器?
- javascript - 我可以将 itemscope 与内容分开吗?