Phi*_*rdi 6 hibernate-validator jackson bean-validation
假设我有一个简单的POJO,如下面注释了Jackson 2.1和Hibernate Validator 4.3.1注释:
final public class Person {
@JsonProperty("nm")
@NotNull
final public String name;
public Person(String name) {
this.name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
我将这样的JSON发送到Web服务:
{"name": null}
Run Code Online (Sandbox Code Playgroud)
报告ConstraintViolation时,Hibernate使用类成员标识符"name"而不是JsonProperty注释值.有谁知道是否可以让Hibernate Validator查看类的注释并使用该值代替?
不幸的是,没有简单的方法可以做到这一点。但是,以下一些见解可以为您提供帮助:
从中ConstraintViolationException,您可以获得一组ConstraintViolation,它公开了违反约束的上下文:
ConstraintViolation#getLeafBean():如果它是bean约束,则此方法返回在其中应用约束的bean实例。ConstraintViolation#getPropertyPath():返回无效属性的路径。 从属性路径中,您可以获取叶节点:
Path propertyPath = constraintViolation.getPropertyPath();
Optional<Path.Node> leafNodeOptional =
StreamSupport.stream(propertyPath.spliterator(), false).reduce((a, b) -> b);
Run Code Online (Sandbox Code Playgroud)
然后检查节点的类型是否为PROPERTY并获取其名称:
String nodeName = null;
if (leafNodeOptional.isPresent()) {
Path.Node leafNode = leafNodeOptional.get();
if (ElementKind.PROPERTY == leafNode.getKind()) {
nodeName = leafNode.getName();
}
}
Run Code Online (Sandbox Code Playgroud)
要从叶子bean类中获取可用的JSON属性,可以使用Jackson进行内省(请参阅此答案和此答案以获取更多详细信息):
Class<?> beanClass = constraintViolation.getLeafBean().getClass();
JavaType javaType = mapper.getTypeFactory().constructType(beanClass);
BeanDescription introspection = mapper.getSerializationConfig().introspect(javaType);
List<BeanPropertyDefinition> properties = introspection.findProperties();
Run Code Online (Sandbox Code Playgroud)
然后通过将叶子节点名称与的Field名称进行比较来过滤属性BeanPropertyDefinition:
Optional<String> jsonProperty = properties.stream()
.filter(property -> nodeName.equals(property.getField().getName()))
.map(BeanPropertyDefinition::getName)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
使用JAX-RS(如果正在使用它),可以定义一个ExceptionMapper来处理ConstraintViolationExceptions:
@Provider
public class ConstraintViolationExceptionMapper
implements ExceptionMapper<ConstraintViolationException> {
@Override
public Response toResponse(ConstraintViolationException exception) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
要在ObjectMapper中使用ExceptionMapper,您可以为其提供一个ContextResolver<T>:
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperContextResolver() {
mapper = createObjectMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
private ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
}
Run Code Online (Sandbox Code Playgroud)
将Providers接口注入您的ExceptionMapper:
@Context
private Providers providers;
Run Code Online (Sandbox Code Playgroud)
查找您ContextResolver<T>的ObjectMapper实例,然后获取实例:
ContextResolver<ObjectMapper> resolver =
providers.getContextResolver(ObjectMapper.class, MediaType.WILDCARD_TYPE);
ObjectMapper mapper = resolver.getContext(ObjectMapper.class);
Run Code Online (Sandbox Code Playgroud)
如果您有兴趣获取@XxxParam姓名,请参考此答案。
不,那不可能。Hibernate Validator 5(Bean Validation 1.1)具有 s 的概念ParameterNameProvider,它在违反方法参数约束的情况下返回要报告的名称,但对于属性约束没有可比性。
| 归档时间: |
|
| 查看次数: |
2783 次 |
| 最近记录: |