Jackson derealization with Spring Boot:获取请求中存在的字段名称以及相应的字段映射

Jackson derealization with SpringBoot : To get field names present in request along with respective field mapping

我需要在不同的情况下抛出不同的错误,像下面这样,而且有很多这样的字段,不仅仅是 1.

例如

  1.    {
        "id": 1,
        "name": "nameWithSpecialChar$"
       }    
    

    这里应该会抛出特殊字符的错误。

  2.    {
         "id": 1,
          "name": null
       }   
    

    此处抛字段空错误

  3.    {
        "id": 1
       }   
    

    这里抛出字段缺失错误

处理,第一个和第二个场景很简单,但是对于第三个场景,有没有什么方法可以让我们在使用 Jackson 进行序列化时获得输入 json 中传递的字段名称列表?

我能够做到的一种方法是通过将请求映射到 JsonNode,然后检查是否存在所需字段的节点,然后手动反序列化该 JsonNode,然后如下验证其余成员。

    public ResponseEntity myGetRequest(@RequestBody JsonNode requestJsonNode) {

    if(!requestJsonNode.has("name")){
      throw some error;
    }

    MyRequest request = ObjectMapper.convertValue(requestJsonNode, MyRequest .class);
    validateIfFieldsAreInvalid(request);

但是我不喜欢这种方式,请问还有其他方式吗?

您可以定义一个 JSON schema 并根据它验证您的对象。在您的示例中,您的架构可能如下所示:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": {
      "description": "The identifier",
      "type": "integer"
    },
    "name": {
      "description": "The item name",
      "type": "string",
      "pattern": "^[a-zA-Z]*$"
    }
  },
  "required": [ "id", "name" ]
}

要验证您的对象,您可以使用 json-schema-validator 库。这个库是建立在 Jackson 之上的。由于您正在使用 Spring Boot,因此您已经导入了 Jackson。

示例代码大致如下所示:

String schema = "<define your schema here>";
String data = "<put your data here>";

JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
ObjectMapper m = new ObjectMapper();
JsonSchema jsonSchema = factory.getJsonSchema(m.readTree(schema));
JsonNode json = m.readTree(data);
ProcessingReport report = jsonSchema.validate(json);

System.out.println(report);

报告包含不同输入案例的详细错误。例如,使用此输入

{
  "id": 1,
  "name": "nameWithSpecialChar$"
}

此输出被打印出来

--- BEGIN MESSAGES ---
error: ECMA 262 regex "^[a-zA-Z]*$" does not match input string "nameWithSpecialChar$"
    level: "error"
    schema: {"loadingURI":"#","pointer":"/properties/name"}
    instance: {"pointer":"/name"}
    domain: "validation"
    keyword: "pattern"
    regex: "^[a-zA-Z]*$"
    string: "nameWithSpecialChar$"
---  END MESSAGES  ---

或者不只是打印报告,您可以遍历所有错误并拥有您的特定逻辑

for (ProcessingMessage message : report) {
    // Add your logic here
}

您可以查看 example code 以获得有关如何使用该库的更多信息。