Набор данных, не проваливающий валидацию по схеме JSON.

Вопрос или проблема

У меня есть базовая схема и расширенная схема ниже

./resources/json-schemas/simple-person.schema

{
  "$id": "http://example.com/json-schemas/simple-person.schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Простой человек",
  "type": "object",
  "people": {
    "items": {
      "properties": {
        "name": {
          "type": "string",
          "description": "Имя человека."
        },
        "age": {
          "type": "integer",
          "description": "Возраст человека."
        }
      },
      "required": [
        "name",
        "age"
      ]
    }
  }
}

./extended-person.schema

{
  "$id": "http://example.com/extended-person.schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Расширенный человек",
  "type": "object",
  "allOf": [
    {
      "$ref": "http://example.com/json-schemas/simple-person.schema"
    },
    {
      "people": {
        "items": {
          "properties": {
            "height": {
              "type": "number",
              "description": "Рост человека в сантиметрах."
            },
            "required": [
              "height"
            ]
          }
        }
      }
    }
  ]
}

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

./person-dataset.json

{
    "people": [
        {
            "name": "Боб",
            "age": 25,
            "new value": "значение"
        }
    ]
}

Я ожидал, что валидация будет неудачной, но она проходит с помощью кода ниже

from pathlib import Path

import json

from referencing import Registry, Resource
from referencing.exceptions import NoSuchResource
from jsonschema import Draft202012Validator


def retrieve_from_filesystem(uri: str):
    SCHEMAS = Path("./resources/json-schemas/")

    if uri.startswith("http://example.com/json-schemas/"):
        path = SCHEMAS / Path(uri.removeprefix("http://example.com/json-schemas/"))
    else:
        raise NoSuchResource(ref=uri)

    contents = json.loads(path.read_text())

    return Resource.from_contents(contents)

registry = Registry(retrieve=retrieve_from_filesystem)

schema = json.load(Path("./extended-person.schema").open())
instance = json.load(Path("./person-dataset.json").open())
validator = Draft202012Validator(schema, registry=registry)

validator.validate(instance)

Я ожидал, что это провалится по двум причинам

  1. в набор данных не включено свойство “height”
  2. в набор данных включено новое свойство “new value”, которое не указано в.schemas

Как мне это исправить, чтобы наборы данных, подобные этому, проваливались?

Ответ или решение

Для решения вашей проблемы с валидацией JSON-данных на основе расширенной схемы, необходимо внести несколько изменений в вашу схему и, возможно, в код, чтобы гарантировать, что экземпляры данных не проходят валидацию, если они содержат свойства, которые не предусмотрены схемой.

1. Исправление схемы

Сначала вам нужно убедиться, что в вашей расширенной схеме extended-person.schema правильно определены все необходимые свойства. В частности, вам нужно добавить свойства required на уровень объектов, содержащих свойство people, чтобы указать, что наличие свойства height обязательно.

{
  "$id": "http://example.com/extended-person.schema",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Extended Person",
  "type": "object",
  "allOf": [
    {
      "$ref": "http://example.com/json-schemas/simple-person.schema"
    },
    {
      "type": "object",
      "properties": {
        "people": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "height": {
                "type": "number",
                "description": "The person's height in centimeters."
              }
            },
            "required": ["height"]
          }
        }
      },
      "required": ["people"]
    }
  ]
}

2. Изменение логики валидации

В вашей текущей реализации валидации JSON-данных:

validator = Draft202012Validator(schema, registry=registry)
validator.validate(instance)

Данная инструкция не генерирует исключения, если данные не соответствуют требованиям вашей схемы. Для того чтобы отлавливать ошибки валидации, вы можете использовать блок try...except и функцию validator.iter_errors(instance) для корректного отображения ошибок валидации.

Вот пример кода с измененной логикой обработки ошибок:

try:
    for error in validator.iter_errors(instance):
        print(error.message)
    print("Validation passed.")
except Exception as e:
    print(f"Validation failed: {e}")

3. Ожидаемое поведение

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

  • Валидация должна не проходить, если в данных отсутствует свойство height.
  • Валидация должна также не проходить, если в данных содержатся дополнительные свойства, которые не предусмотрены схемой, такие как new value.

4. Заключение

С учетом вышеизложенного, теперь схема и код должны корректно обрабатывать случай, когда JSON-данные не соответствуют ожиданиям. Проверьте эти изменения и, надеюсь, это решит вашу проблему с валидацией. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.

Оцените материал
Добавить комментарий

Капча загружается...