JSON Схема валидатора Выбор валидаторов - PullRequest
0 голосов
/ 05 марта 2020

Моя проблема заключается в том, как мне получить библиотеку json -schema-validator , чтобы фактически проверить ответ JSON относительно схемы JSON, которую я определил. Моя цель - заставить работать "дополнительные свойства" и проверку типов полей. То есть проверка отклоняет неизвестные поля и проверяет, чтобы числовые значения не содержали строк и т. Д. c.

Файлы, код и справочная информация следуют.

Схема Swagger 2.0 стандартное определение

Схема Учащиеся Определение API

{
  "swagger": "2.0",
  "info": {
    "title": "Students API",
    "description": "Operations on Students",
    "version": "1.0"
  },
  "basePath": "/v1/students",
  "schemes": [
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json",
    "application/xml"
  ],
  "paths": {
    "/{UID}": {
      "get": {
        "tags": [
          "students"
        ],
        "summary": "Get information about a Students Member.",
        "description": "Given an University ID, return information for the identified students member.",
        "operationId": "getStudentsByUID",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "required": true,
            "name": "UID",
            "in": "path",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "OK. The operation was successful.",
            "schema": {
              "$ref": "#/definitions/Students"
            }
          },
          "204": {
            "description": "No Content. No Students the UID"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Not Authorised"
          },
          "405": {
            "description": "Method Not Allowed"
          },
          "429": {
            "description": "Too Many Requests"
          },
          "500": {
            "description": "Internal Server Error"
          }
        }
      }
    }
  },
  "definitions": {
    "Students": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "Status": {
          "$ref": "#/definitions/Status"
        },
        "Person": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Person"
          }
        }
      }
    },
    "Status": {
      "type": "object",
        "additionalProperties": false,
      "properties": {
        "StatusCode": {
          "type": "integer"
        },
        "Reason": {
          "type": "string"
        }
      },
      "required": [
        "StatusCode",
        "Reason"
      ]
    },
    "Person": {
      "type": "object",
      "description": "Representation of a person record for a student",
      "properties": {
        "PersonIdentifiers": {
          "type": "object",
          "properties": {
            "Identifier": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Identifier"
              }
            }
          }
        },
        "PersonNames": {
          "$ref": "#/definitions/PersonNames"
        },
        "AcademicPlanDetails": {
          "type": "object",
          "properties": {
            "AcademicPlanDetail": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/AcademicPlanDetail"
              }
            }
          }
        }
      }
    },
    "Identifier": {
      "type": "object",
      "properties": {
        "IdentifierType": {
          "type": "string"
        },
        "IdentifierValue": {
          "type": "string"
        }
      }
    },
    "PersonNames": {
      "type": "object",
      "properties": {
        "FirstName": {
          "type": "string"
        },
        "MiddleName": {
          "type": "string"
        },
        "LastName": {
          "type": "string"
        },
        "Title": {
          "type": "string",
          "enum": [
            "Mr",
            "Mrs",
            "Ms",
            "Master",
            "Dr"
          ]
        },
        "NameSuffixes": {
          "description": "Not applicable to all Persons",
          "type": "string",
          "enum": [
            "Jr",
            "CPA",
            "Esq",
            "Ph.D"
          ]
        },
        "FullName": {
          "type": "string"
        },
        "PreferredName": {
          "description": "Not applicable to all Persons",
          "type": "string"
        },
        "LongName": {
          "type": "string"
        },
        "AliasName": {
          "description": "Not applicable to all Persons",
          "type": "string"
        },
        "Pronunciation": {
          "description": "Not applicable to all Persons",
          "type": "string"
        }
      }
    },
    "AcademicPlanDetail": {
      "type": "object",
      "properties": {
        "AcademicCareer": {
          "type": "string"
        },
        "StudentCareerNumber": {
          "type": "string"
        },
        "EffectiveDate": {
          "type": "string"
        },
        "EffectiveSequence": {
          "type": "string"
        },
        "AcademicProgram": {
          "type": "string"
        },
        "AcademicProgramDescription": {
          "type": "string"
        },
        "AcademicPlan": {
          "type": "string"
        },
        "AcademicPlanDescription": {
          "type": "string"
        },
        "AcademicSubPlan": {
          "type": "string"
        },
        "AcademicSubPlanDescription": {
          "type": "string"
        },
        "ProgramStatus": {
          "type": "string"
        },
        "ProgramStatusDescription": {
          "type": "string"
        },
        "ProgramAction": {
          "type": "string"
        },
        "ProgramActionDescription": {
          "type": "string"
        },
        "ProgramReason": {
          "type": "string"
        },
        "ProgramReasonDescription": {
          "type": "string"
        },
        "AdmittedTerm": {
          "type": "string"
        },
        "ResearchStudentCandidateNumber": {
          "type": "string"
        }
      }
    }
  },
  "tags": [
    {
      "name": "api-metadata",
      "description": "Information about the API including its terms of use"
    },
    {
      "name": "students",
      "description": "Operations on all types of University students"
    }
  ]
}

Ответ ученика Хороший Действительное ответное сообщение

{
  "Status": {
    "StatusCode": 200,
    "Reason": "OK",
  },
  "Person": [
    {
      "PersonIdentifiers": {
        "Identifier": [
          {
            "IdentifierType": "UniversityID",
            "IdentifierValue": "12345678"
          },
          {
            "IdentifierType": "EmailAddress",
            "IdentifierValue": "JohnSmith@no.such.org"
          },
          {
            "IdentifierType": "PositionNumber",
            "IdentifierValue": "00006789"
          }
        ]
      },
      "PersonNames": {
        "PreferredName": "",
        "FirstName": "Johnathon",
        "MiddleName": "",
        "LastName": "Smith",
        "Title": "Dr",
        "NameSuffixes": "",
        "FullName": "Smith,Jonathon",
        "LongName": "",
        "AliasName": "",
        "Pronunciation": ""
      },
      "AcademicPlanDetails": {
        "AcademicPlanDetail": [
          {
            "AcademicCareer": "RSCH",
            "StudentCareerNumber": "0",
            "EffectiveDate": "2019-12-19",
            "EffectiveSequence": "1",
            "AcademicProgram": "9876",
            "AcademicProgramDescription": "Arts & Social Sciences",
            "AcademicPlan": "9876XPHD",
            "AcademicPlanDescription": "School of Humanities and the Arts",
            "AcademicSubPlan": "HUMAN",
            "AcademicSubPlanDescription": "Humanities",
            "ProgramStatus": "AC",
            "ProgramStatusDescription": "Active",
            "ProgramAction": "MATR",
            "ProgramActionDescription": "Matriculate",
            "ProgramReason": "ACTV",
            "ProgramReasonDescription": "Activated Manually",
            "AdmittedTerm": "1903",
            "ResearchStudentCandidateNumber": "000000034567"
          }
        ]
      }
    }
  ]
}

Ответ ученика плохой Неверное ответное сообщение. Включает нежелательные агрегаты, поля и неправильные типы данных.

{
  "Fred": {
    "Freddy": "Kruger"
  },
  "Status": {
    "StatusCode": "200",
    "Reason": "OK",
    "X-Event-Id": "12340818-5a7c-11ea-920e-0a2835080000-1",
    "Unexpected": "Undefined additional propery"
  },
  "Person": [
    {
      "PersonIdentifiers": {
        "Identifier": [
          {
            "IdentifierType": "UniversityID",
            "IdentifierValue": "12345678"
          },
          {
            "IdentifierType": "EmailAddress",
            "IdentifierValue": "JohnSmith@no.such.org"
          },
          {
            "IdentifierType": "PositionNumber",
            "IdentifierValue": "00006789"
          }
        ]
      },
      "PersonNames": {
        "PreferredName": "",
        "FirstName": "Johnathon",
        "MiddleName": "",
        "LastName": "Smith",
        "Title": "Dr",
        "NameSuffixes": "",
        "FullName": "Smith,Jonathon",
        "LongName": "",
        "AliasName": "",
        "Pronunciation": ""
      },
      "AcademicPlanDetails": {
        "AcademicPlanDetail": [
          {
            "AcademicCareer": "RSCH",
            "StudentCareerNumber": "0",
            "EffectiveDate": "2019-12-19",
            "EffectiveSequence": "1",
            "AcademicProgram": "9876",
            "AcademicProgramDescription": "Arts & Social Sciences",
            "AcademicPlan": "9876XPHD",
            "AcademicPlanDescription": "School of Humanities and the Arts",
            "AcademicSubPlan": "HUMAN",
            "AcademicSubPlanDescription": "Humanities",
            "ProgramStatus": "AC",
            "ProgramStatusDescription": "Active",
            "ProgramAction": "MATR",
            "ProgramActionDescription": "Matriculate",
            "ProgramReason": "ACTV",
            "ProgramReasonDescription": "Activated Manually",
            "AdmittedTerm": "1903",
            "ResearchStudentCandidateNumber": "000000034567"
          }
        ]
      }
    }
  ]
}

Код JSON Схема и JSON Проверка экземпляра

package com.nsd;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;


public class JsvCmd {
    public static final String JSON_V4_SCHEMA_IDENTIFIER = "http://json-schema.org/draft-04/schema#";
    public static final String JSON_SCHEMA_IDENTIFIER_ELEMENT = "$schema";

    public static void main(String[] args) throws IOException, ProcessingException {
        final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();

        // Load the JSON Schema for Swagger 2.0 API definition
        File swaggerSchemaFile = new File("/Users/syntegrity/Documents/AnuStuff/Swagger2.0.json");

        JsonNode jsonNodeSwagger = JsonLoader.fromFile(swaggerSchemaFile);
        JsonNode schemaIdentifierSwagger = jsonNodeSwagger.get(JSON_SCHEMA_IDENTIFIER_ELEMENT);
        if (null != schemaIdentifierSwagger) {
            System.out.println("Swagger Schema Type: " + schemaIdentifierSwagger.asText());
        }

        final JsonSchema jsonSchemaSwagger = factory.getJsonSchema(jsonNodeSwagger);

        // Next load the schema we are interested in and validate it against the Swagger 2.0 API schema
        File userSchemaFile = new File("/Users/syntegrity/Documents/AnuStuff/Students_V1_SO.json");

        JsonNode jsonNodeUserSchema = JsonLoader.fromFile(userSchemaFile);

        ProcessingReport userSchemaReport = jsonSchemaSwagger.validate(jsonNodeUserSchema, true);
        if (!userSchemaReport.isSuccess()) {
            System.out.println("UserSchema is invalid");
            System.out.println(userSchemaReport);

            return;
        }

        // To get the validators we want used happening add a $schema element that specifies IETF Draft-04
        JsonNode schemaIdentifierUser = jsonNodeUserSchema.get(JSON_SCHEMA_IDENTIFIER_ELEMENT);
        if (null == schemaIdentifierUser) {
            ((ObjectNode) jsonNodeUserSchema).put(JSON_SCHEMA_IDENTIFIER_ELEMENT, JSON_V4_SCHEMA_IDENTIFIER);

            System.out.println("User Schema coerced to IETF Draft-04 for validation purposes");
        } else {
            // For what we want to do anything other than a $schema value of IETF Draft-04 is going
            // to cause problems. NOTE: The Swagger 2.0 API schema does not allow $schema anyway
            if (!JSON_V4_SCHEMA_IDENTIFIER.equals(schemaIdentifierUser.asText())) {
                System.out.println("Schema Type: " + schemaIdentifierUser.asText() + " is not " + JSON_V4_SCHEMA_IDENTIFIER);

                return;
            }
        }

        JsonSchema jsonSchemaUser = factory.getJsonSchema(jsonNodeUserSchema);

        // Finally validate the JSON data
        File jsonDataFile = new File("/Users/syntegrity/Documents/AnuStuff/Students_Bad_SO.json");
        JsonNode jsonNodeData = JsonLoader.fromFile(jsonDataFile);

        ProcessingReport userDataReport = jsonSchemaUser.validate(jsonNodeData, true);

        if (!userSchemaReport.isSuccess()) {
            System.out.println(userDataReport);
        } else {
                System.out.println("Sweet");
        }
    }
}

pom. xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.nsd</groupId>
    <artifactId>jsvcmd</artifactId>
    <version>1.0.0</version>
    <name>JsonValidator</name>
    <description>JSON Validator Command Line</description>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.atlassian.oai/swagger-request-validator -->
        <dependency>
        <groupId>com.github.fge</groupId>
        <artifactId>json-schema-validator</artifactId>
        <version>2.2.6</version>
        </dependency>
        <dependency>
        <groupId>com.github.fge</groupId>
        <artifactId>jackson-coreutils</artifactId>
        <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Результаты прогона

Swagger Schema Type: http://json-schema.org/draft-04/schema#
User Schema coerced to IETF Draft-04 for validation purposes
Sweet

Я надеялся увидеть следующие ошибки, а не "Sweet"

  • Нежелательный: [Фред]
  • Нежелательный: [X-Event-Id]
  • Нежелательный: [Неожиданный]
  • "200" не имеет целочисленный тип

Отладка

При изменении "производит" на "производитx" в схеме студентов я получаю следующий вывод.

UserSchema is invalid
com.github.fge.jsonschema.core.report.ListProcessingReport: failure
--- BEGIN MESSAGES ---
error: object instance has properties which are not allowed by the schema: ["producesx"]
    level: "error"
    schema: {"loadingURI":"#","pointer":""}
    instance: {"pointer":""}
    domain: "validation"
    keyword: "additionalProperties"
    unwanted: ["producesx"]
---  END MESSAGES  ---

Поэтому, когда я использую схему Swagger 2.0 для проверки моей схемы учеников после того, как она становится недействительной, я получаю сообщение об ошибке. Yay.

Это не тот случай, когда я пытаюсь использовать Схему ученика для проверки Плохой ответ ученика .

После того, как я очень расстроился решите использовать Java Debug для входа в библиотеки json -schema-validator и json -schema-core.

В InstanceValidator.class, см. скриншоты ниже, я обнаружил, что для первого jsonSchemaSwagger.validate (jsonNodeUserSchema, true); вызов содержит три валидатора, связанных с объектом fullContext, тогда как во втором jsonSchemaUser.validate (jsonNodeData, true); вызов не связан с валидаторами к объекту fullContext. Я уверен, что это означает, что проверка не будет.

Первый звонок enter image description here

InstanceValidator.class enter image description here

Три валидатора AdditionalPropertiesValidator, RequiredKeywordValidator и DraftV4TypeValidator enter image description here

Второй вызов enter image description here

Нет валидаторов enter image description here

Наконец

И так, наконец, к вопросу. Какие звонки мне нужно сделать, чтобы использовать тот же набор валидаторов для моего второго проверочного звонка? Т.е. как создать список валидаторов и затем выполнить их для данных экземпляра JSON?

...