java - 用于更新具有空值或 null 值的信息的 REST API

标签 java rest jackson resteasy

我有一个关于如何最好地构建可以修改数据库中记录的 API 的一般性问题。

假设我们有一个包含 10 列的表,我们可以使用 REST (GET) 查询这 10 列。 JSON 响应将包含所有 10 个字段。这很简单并且没有问题。

下一步是有人想要通过 POST 创建新记录。在这种情况下,该人仅发送 JSON 请求中 10 个字段中的 8 个。然后我们只填充数据库中的 8 个字段(其余为 NULL)。这也没有问题。

但是如果有人想要更新记录怎么办?我们在这里看到了不同的可能性,各有优缺点。

  1. 仅发送应更新的内容。 问题:如何显式清空/删除字段?如果在 JSON 中传递“NULL”,我们会在对象中得到 NULL,但任何其他未传递的字段也为 NULL。因此我们无法区分哪些字段可以删除,哪些字段不能触及。

  2. 完整的对象已发送。 问题:这里的对象之前可以通过 GET 获取,相应地更改并通过 PUT 返回。现在我们取回了所有信息,并且可以将信息直接写回到数据库中。因为空字段要么之前已经为空,要么被用户清除。

如果对象通过 API 更新进行扩展,会发生什么情况。假设我们将数据库再扩展五个字段。 API 的用户进行 GET,获取 15 个字段,但只能读取他页面上他知道的 10 个字段(因为他还没有更新他的一侧)。然后他更改了 10 个字段中的一些字段并通过 PUT 将它们发回。然后,我们将仅更新网站上的 10 个字段,并且 5 个新字段将从数据库中清空。

或者您是否必须为每个字段创建一个单独的端点?我们也考虑过创建一个带有键/值的映射,到底应该改变什么。

关于技术:我们使用 Wildfly 15 以及 Resteasy 和 Jackson

例如:

开头的数据库

+----+----------+---------------+-----+--------+-------+
| ID | Name     | Country       | Age | Weight | Phone |
+----+----------+---------------+-----+--------+-------+
| 1  | Person 1 | Germany       | 22  | 60     | 12345 |
| 2  | Person 2 | United States | 32  | 78     | 56789 |
| 3  | Person 3 | Canada        | 52  | 102    | 99999 |
+----+----------+---------------+-----+--------+-------+

获取.../人/2

{
   "id" : 2,
   "name" : "Person 2",
   "country" : "United States",
   "age" : 22,
   "weight" :62,
   "phone": "56789"
}

现在我想更新他的体重并删除电话号码

放置.../人/2

{
   "id" : 2,
   "name" : "Person 2",
   "country" : "United States",
   "age" : 22,
   "weight" :78
}

{
   "id" : 2,
   "name" : "Person 2",
   "country" : "United States",
   "age" : 22,
   "weight" :78,
   "phone" : null
}

现在数据库应该如下所示:

+----+----------+---------------+-----+--------+-------+
| ID | Name     | Country       | Age | Weight | Phone |
+----+----------+---------------+-----+--------+-------+
| 1  | Person 1 | Germany       | 22  | 60     | 12345 |
| 2  | Person 2 | United States | 32  | 78     | NULL  |
| 3  | Person 3 | Canada        | 52  | 102    | 99999 |
+----+----------+---------------+-----+--------+-------+

问题是

我们像这样扩展表格(salery)

+----+----------+---------------+-----+--------+--------+-------+
| ID | Name     | Country       | Age | Weight | Salery | Phone |
+----+----------+---------------+-----+--------+--------+-------+
| 1  | Person 1 | Germany       | 22  | 60     | 1929   | 12345 |
| 2  | Person 2 | United States | 32  | 78     | 2831   | NULL  |
| 3  | Person 3 | Canada        | 52  | 102    | 3921   | 99999 |
+----+----------+---------------+-----+--------+--------+-------+

使用 API 的人不知道 JSON 中有一个用于工资的新字段。而这个人现在又想换别人的电话号码,却不发工资。这也会清空工资:

{
   "id" : 3,
   "name" : "Person 3",
   "country" : "Cananda",
   "age" : 52,
   "weight" :102,
   "phone" : null
}


+----+----------+---------------+-----+--------+--------+-------+
| ID | Name     | Country       | Age | Weight | Salery | Phone |
+----+----------+---------------+-----+--------+--------+-------+
| 1  | Person 1 | Germany       | 22  | 60     | 1929   | 12345 |
| 2  | Person 2 | United States | 32  | 78     | 2831   | NULL  |
| 3  | Person 3 | Canada        | 52  | 102    | NULL   | NULL  |
+----+----------+---------------+-----+--------+--------+-------+

薪水不应该为空,因为它没有在 JSON 请求中设置

最佳答案

您可以将 JSON 反序列化为 Map。 这样,如果属性尚未发送,则该属性不会出现在 Map 中。如果为空,则其在 map 内将为空值。

  ObjectMapper mapper = new ObjectMapper();
  TypeReference<HashMap<String, Object>> typeReference = new TypeReference<>() {};
  HashMap<String, Object> jsonMap = mapper.readValue(json, typeReference);
  jsonMap.entrySet().stream().map(Map.Entry::getKey).forEach(System.out::println);

这不是一个非常方便的解决方案,但它可能适合您。

关于java - 用于更新具有空值或 null 值的信息的 REST API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59625400/

相关文章:

rest - RSpec "No routes matches"

asp.net - 是否可以在 ASP.NET 5 的 Web API 中使用外部身份提供程序?

java - Jackson 使用 Enum Key 和 POJO Value 反序列化为 Map

json - 如何将对象转换为 Jooq JSON

java - 使用此运算符通过接口(interface)强制转换实现的类

java - 应用程序访问不同的数据库

java - 如何将创建的对象传递给另一个Java类

java - Maven 和常规 Java 可以在单个 eclipse 项目中使用

java - Jersey 客户端日志响应和 getEntity

java - 使用 Jackson 从 JSON 树中的特定节点映射对象