Java 中的 REST API - 如何使用 Hibernate Validator 支持 PATCH

问题描述 投票:0回答:1

在 Java 中编写 REST-API 时,PATCH 方法请求将请求实体中描述的一组“更改”应用于由 Request-URI 标识的资源。 (参见:https://datatracker.ietf.org/doc/html/rfc5789

给出以下资源:

{
  productId: 7,
  name: "container",
  contactPerson: "peter",
  price: 12
}

使用 PATCH,我应该能够将“contactPerson”设置为 NULL,同时不触及其他字段,如下所示:

{
  productId: 7,
  contactPerson: null
}

在 Java 生态系统中,考虑到这里最相关的库需要对其提供全面支持,我如何才能以良好的方式实现这一点:

  • Jackson(JSON 反序列化)
  • Hibernate 验证器(Bean 验证)
  • Microprofile OpenAPI(API 定义)

Java 可选

除其他外,我尝试了 Java-Optional,虽然它最初似乎有效,但它是错误的工具,因为可选不应该包含 NULL 值,但也应该可以在内部显式地将值设置为 NULL一个补丁(而不是省略它)。

  • 但我确实在使用Optional 方面取得了很大进展。唯一的问题是 Hibernate Validator 不支持我需要的方式。

例如,以下内容最初看起来不错(此处为必需的名称字段 = false 且可空 = false):

@Schema(required = false, nullable = false)
Optional<@NotNull @Size(max = 255) String> name = Optional.empty();

当请求中缺少名称字段时,Hibernate 验证器认为违反了 @NotNull 注释,我觉得这很奇怪,因为注释位于可选通用声明中(而不是直接在可选中)

JsonNullable

Jackson 提供了 JsonNullable 注释。虽然这是完成该任务的正确工具,并且似乎支持 openapi,但它似乎不支持 hibernate validator,至少我找不到有关它的信息。

验证

问题似乎主要出在 Bean 验证注释的验证过程中,这对于 API 来说很重要。

  • 当使用
    @Size(255)
    @Email
    等注释时,有要求......
    • ...当在 PATCH 中给出/设置字段时,这些验证必须由 Hibernate 验证器进行验证
    • ...当 PATCH 中省略(缺失)该字段时,不得验证这些验证。

--

Java 生态系统的那些主要库是否涵盖了 REST-PATCH?如果是,建议的支持方式是什么?

java rest jackson openapi hibernate-validator
1个回答
0
投票

如何在请求正文中获取键值映射,其中键与字段名称匹配。

@PatchMapping("/boxes/{id}")
public Box patchBox(@PathVariable Long id, @RequestBody Map<String, Object> values) throws JsonMappingException {
    return boxService.patchBox(id, values);
}

那么字段值为空的情况将不会与请求中缺少该字段的情况重叠,并且您可以使用ObjectMapper自动仅更新请求中传入的那些字段。

@Override
@Transactional
public Box patchBox(Long id, Map<String, Object> values) throws JsonMappingException {
    Box box = entityManager.find(Box.class, id);
    objectMapper.updateValue(box, values);
    return box;
}

当然,您无法验证查询中的字段值,但您会自动验证其字段更新为这些值的实体。问问自己,如果查询中的字段值的正确性取决于不在查询中的另一个字段的值,如何验证该字段值。

© www.soinside.com 2019 - 2024. All rights reserved.