Валидация JSON-схем#

В Schema Registry реализована возможность валидации JSON-схем, при этом данные в схеме проверяются на соответствие следующим правилам:

  • в схемах длина элементов типа string должна быть не более 4096 символов;

  • в схемах длина элементов типа array должна быть не более 4096 символов;

  • в схемах длина элементов типа properties должна быть не более 4096 символов;

  • схема должна быть на основе версии стандарта JSON Schema не ниже draft-4;

  • для каждой сущности типа object необходимо указывать additionalProperties со значением либо false, либо json-schema для значений дополнительных свойств. Если значением additionalProperties является схема, то необходимо использовать maxProperties для ограничения количества дополнительных свойств и перечислить их возможные типы с обязательными для этих типов ограничениями. Также необходимо описать состав передаваемых данных;

  • при использовании patternProperties необходимо указать максимальное число дополнительных свойств maxProperties, ограничить имя свойства по длине (не более 255 символов), перечислить возможные типы с обязательными для этих типов ограничениями. Также необходимо описать состав передаваемых данных. При таком подходе ограничение "additionalProperties": false по-прежнему является обязательным;

  • перечень обязательных параметров должен заключаться в свойство required для каждого элемента с дочерними узлами. Все обязательные элементы required должны быть указаны массивом, а не флагом;

  • для передачи массива следует явно указать в items типы элементов массива и использовать флаг "additionalItems": false и "uniqueItems": true. Если все элементы массива (в том числе и object) — одного типа, то items должен быть объектом, описывающим тип элемента, при этом флаг additionalItems может не использоваться;

  • для передачи в схемах даты в элементах типа string должен использоваться шаблон "pattern": "^\\d{4}-\\d{2}-\\d{2}$";

  • для передачи в схемах даты и времени в элементах типа string должен использоваться шаблон "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(\\.[\\d]{1,6})?(([+-]\\d\\d:\\d\\d)|Z)?$";

  • для передачи целочисленных значений следует использовать "type": "integer" с указанием минимального и максимального значений ("minimum" и "maximum"). Минимальное и максимальное значения должны быть в диапазоне: -2^53 + 1 и 2^53 - 1;

  • для передачи значений с плавающей точкой следует использовать "type": "number" с указанием минимального и максимального значений ("minimum" и "maximum"). Минимальное и максимальное значения должны быть в диапазоне: -2^53 + 1 и 2^53 - 1.

Валидация осуществляется на стороне сервера Schema Registry, после того как пришел запрос на создание новой схемы от клиента. Если схема не удовлетворяет вышеуказанным требованиям, то данная схема создана не будет.

По умолчанию валидация JSON-схем отключена.

Включение валидации JSON-схем#

Для включения валидации JSON-схем по приведенным выше требованиям необходимо в файл schema-registry.properties добавить параметр:

schema.registry.rest.schemas.custom.checks=true

Пример валидации схемы#

Пример невалидной схемы:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/mySchema.json",
  "type": "object",
  "properties": {
    "type": {
      "type": ["number", "string"]
    }
  },
  "additionalProperties": {
    "type": "object",
    "properties": {
      "property1": {
        "type": "string"
      },
      "property2": {
        "type": "number"
      }
    },
      "required": ["property1"]
    },
    "required": ["type"]
}

При попытке создания данной схемы через curl получим следующее сообщение об ошибке:

{"error_code": 422, "message": "invalid schema: java.lang.RuntimeException:
ERROR: application-45 additionalProperties must be false or object schema[location=#],
ERROR: application-45 maxProperties must be specified[location=#],
ERROR: application-45 additionalProperties must be false or object schema[location=#/additionalProperties],
ERROR: application-51 minimum must be specified[location=#/additionalProperties/properties/property2],
ERROR: application-51 maximum must be specified[location=#/additionalProperties/properties/property2],
ERROR: application-36 Max length exceed[max=4096, actual=null, location=#/additionalProperties/properties/property1]"
}

В лог-файле сервера Schema Registry schema-registry.log будут следующие сообщения:

[2023-08-08 16:17:51,548][http-nio-8081-exec-6] INFO SubjectController.create[subj=new-value,type=JSON] (ru.sbrf.kafka.schemaregistry.rest.SubjectController)
[2023-08-08 16:17:51,549][http-nio-8081-exec-6] WARN Error (ru.sbrf.kafka.schemaregistry.rest.ResponseExceptionHandler)
ru.sbrf.kafka.schemaregistry.schemas.InvalidSchemaException: java.lang.RuntimeException:
ERROR: application-45 additionalProperties must be false or object schema[location=#],
ERROR: application-45 maxProperties must be specified[location=#],
ERROR: application-45 additionalProperties must be false or object schema[location=#/additionalProperties],
ERROR: application-51 minimum must be specified[location=#/additionalProperties/properties/property2],
ERROR: application-51 maximum must be specified[location=#/additionalProperties/properties/property2],
ERROR: application-36 Max length exceed[max=4096, actual=null, location=#/additionalProperties/properties/property1]
at ru.sbrf.kafka.schemaregistry.rest.SubjectController.create(SubjectController.java:153)

Пример исправленной схемы, которая пройдет валидацию и будет создана:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/mySchema.json",
  "type": "object",
  "properties": {
    "type": {
      "type": ["number", "string"],
      "allOf": [
        {
          "type": "number",
          "minimum": 9.99,
          "maximum": 9999.99
        },
        {
          "type": "string",
          "maxLength": 10
        }
      ]
    }
  },
  "additionalProperties": {
    "type": "object",
    "properties": {
      "property1": {
        "type": "string",
        "maxLength": 1000
      },
      "property2": {
        "type": "number",
        "minimum": 9.99,
        "maximum": 9999.99
      }
    },
    "required": ["property1"],
    "maxProperties": 10,
    "additionalProperties": false
  },
  "required": ["type"]
}