gpt4 book ai didi

jackson - 休眠验证器和 jackson : Using the @JsonProperty value as the ConstraintViolation PropertyPath?

转载 作者:行者123 更新时间:2023-12-04 05:03:09 25 4
gpt4 key购买 nike

假设我有一个简单的 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;
}
}

我将这样的 JSON 发送到 Web 服务:
{"name": null}

当它报告 ConstraintViolation 时,休眠使用类成员标识符“名称”而不是 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);

    然后检查节点的类型是否为 PROPERTY 并得到它的名字:

    String nodeName = null;

    if (leafNodeOptional.isPresent()) {
    Path.Node leafNode = leafNodeOptional.get();
    if (ElementKind.PROPERTY == leafNode.getKind()) {
    nodeName = leafNode.getName();
    }
    }

    与 jackson 一起自省(introspection)一个类

    要从叶 bean 类中获取可用的 JSON 属性,您可以使用 Jackson 对其进行自省(introspection)(参见 answeranswer 了解更多详细信息):

    Class<?> beanClass = constraintViolation.getLeafBean().getClass();
    JavaType javaType = mapper.getTypeFactory().constructType(beanClass);

    BeanDescription introspection = mapper.getSerializationConfig().introspect(javaType);
    List<BeanPropertyDefinition> properties = introspection.findProperties();

    然后通过将叶节点名称与 Field 进行比较来过滤属性来自 BeanPropertyDefinition 的名称:

    Optional<String> jsonProperty = properties.stream()
    .filter(property -> nodeName.equals(property.getField().getName()))
    .map(BeanPropertyDefinition::getName)
    .findFirst();

    使用 JAX-RS?

    使用 JAX-RS(如果您正在使用它),您可以定义 ExceptionMapper 处理 ConstraintViolationException 年代:

    @Provider
    public class ConstraintViolationExceptionMapper
    implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException exception) {
    ...
    }
    }

    使用 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;
    }
    }

    注入(inject) Providers 您的 ExceptionMapper 中的界面:

    @Context
    private Providers providers;

    查找您的 ContextResolver<T> 然后得到 ObjectMapper 实例:

    ContextResolver<ObjectMapper> resolver = 
    providers.getContextResolver(ObjectMapper.class, MediaType.WILDCARD_TYPE);
    ObjectMapper mapper = resolver.getContext(ObjectMapper.class);

    如果您有兴趣获取 @XxxParam名称,请参阅此 answer .

    关于jackson - 休眠验证器和 jackson : Using the @JsonProperty value as the ConstraintViolation PropertyPath?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18878868/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com