Многоразовые определения json сложной схемы, проверки $ ref во вложенных свойствах игнорируются - PullRequest
1 голос
/ 24 мая 2019

Попытка изучить схемы JSON, и у меня сложная схема, основанная на относительных URL.Когда вложенные свойства вызывают свойство определения, определенное в другом файле, проверки иногда игнорируются.

Моя цель состоит в том, чтобы в основном сделать повторно используемые определения и часто используемые перечисления / константы / определения глобально

Предположим, дерево проекта:

-------------------------------------------
| C:/project                              |
| `----main.json (file to be validated)   |
| `----/schemas                           |
|   `----base.json                        |
|   `----datatypes.json                   |
|   `----defs.json                        |
|   `----frequent.json                    |
|   `----/pii                             |
|     `----jobs.json                       |
-------------------------------------------

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

datatypes.json

{
  "$id": "http://project.com/schemas/datatypes.json",
  "$schema" : "http://json-schema.org/draft-07/schema",

  "definitions" : {
    "type_number": {
      "type": "number",
      "default": 0.0
    },

    "type_integer": {
      "type": "integer",
      "default": 0
    },

    "type_nonempty_string" : {
      "type": "string",
      "minLength": 1,
      "pattern": "^([^\\s].*[^\\s]*)$"
    }
  }
}

defs.json

{
  "$id": "http://project.com/schemas/defs.json",
  "$schema": "http://json-schema.org/draft-07/schema",
  "definitions": {
    "number": {
      "$ref": "./datatypes.json#/definitions/type_number"
    },
    "null_number": {
      "oneOf": [
        {
          "$ref": "#/definitions/number"
        },
        {
          "type": "null"
        }
      ]
    },
    "positive_number": {
      "$ref": "#/definitions/number",
      "minimum": 0.0
    },
    "positive_nonzero_number": {
      "$ref": "#/definitions/number",
      "exclusiveMinimum": 0.0
    },
    "integer": {"$ref": "./datatypes.json#/definitions/type_integer"},
    "positive_integer" : {
      "$ref": "#/definitions/integer",
      "minimum" : 0
    },
    "positive_nonzero_integer" : {
      "$ref": "#/definitions/integer",
      "exclusiveMinimum" : 0
    },

    "strict_object": {
      "type": "object",
      "additionalProperties": false
    },
    "nonempty_string": {"$ref": "./datatypes.json#/definitions/type_nonempty_string"},
    "nonempty_string_null" : {
      "oneOf": [
        {
          "$ref": "#/definitions/nonempty_string"
        },
        {
          "type": "null"
        }
      ]
    }
  }
}

frequent.json

{
  "$id": "http://project.com/schemas/frequent.json",
  "$schema" : "http://json-schema.org/draft-07/schema",
  "definitions" : {
    "SEX_TYPES" : {
      "enum" : ["Male", "M","Female","F"]
    },
    "STATES" : {
      "$comment" : "assume this is an emum of states in US",
      "enum" : ["AK","AL","CT"]
    },

    "address" : {
      "$ref" : "./defs.json#/definitions/strict_object",
      "required" : ["street1", "city", "state", "zipcode"],
      "properties" : {
        "street1" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
        "street2" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
        "city" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
        "state" : { "$ref" : "#/definitions/STATES" },
        "zipcode" : { "$ref" : "#/definitions/zipcode" }
      }
    },

    "zipcode": {
      "allOf": [
        {
          "$ref": "./defs.json#/definitions/nonempty_string"
        },
        {
          "pattern": "^(\\d{5})$"
        },
        {
          "not": {
            "pattern": "^(00000)$"
          }
        }
      ]
    }
  }
}

base.json

{
  "$id": "http://project.com/schemas/base.json",
  "$schema" : "http://json-schema.org/draft-07/schema",
  "type": "object",
  "$ref": "./defs.json#/definitions/strict_object",
  "properties": {
    "main": {
      "$ref": "./defs.json#/definitions/strict_object",
      "required": ["age", "sex", "empl_num", "description", "address", "jobs"],
      "properties": {
        "age": {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
        "sex": {"$ref": "./frequent.json#/definitions/SEX_TYPES" },
        "empl_num" : {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
        "description": {"$ref": "./defs.json#/definitions/nonempty_string"},
        "jobs" : {"$ref": "pii/jobs.json"},
        "address": {"$ref": "./frequent.json#/definitions/address"}
      }
    }
  }
}

pii/jobs.json

{
  "$id" : "http://project.com/schemas/pii/jobs.json",
  "$schema": "http://json-schema.org/draft-07/schema",
  "type" : "array",
  "minItems": 1,
  "items": {
    "$ref" : "../defs.json#/definitions/strict_object",
    "required": ["description","company","pay_details"],
    "properties" : {
      "description" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
      "company" : {
        "$ref": "../defs.json#/definitions/strict_object",
        "required": ["name","address"],
        "properties": {
          "name" : { "$ref" :  "../defs.json#/definitions/nonempty_string" },
          "address" : {"$ref":  "../frequent.json#/definitions/address"}
        }
      },
      "pay_details" : {
        "$ref" : "../defs.json#/definitions/strict_object",
        "required": ["pay_grade", "salary", "performance_review"],
        "properties": {
          "pay_grade" : { "$ref" : "../defs.json#/definitions/positive_nonzero_integer" },
          "salary" : { "$ref" : "../defs.json#/definitions/positive_nonzero_number" },
          "performance_review" : {
            "$ref" : "../defs.json#/definitions/strict_object",
            "required" : ["previous", "nextDate", "numberOfWriteUps"],
            "properties" : {
              "notes" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
              "numberOfWriteUps" : {"$ref" : "../defs.json#/definitions/positive_integer" },
              "previous" : {
                "$ref" : "../defs.json#/definitions/strict_object",
                "required": ["date", "rating"],
                "properties": {
                  "date" : {
                    "$ref" : "../defs.json#/definitions/nonempty_string",
                    "format" : "date-time"
                  },
                  "rating" : {"$ref" : "../defs.json#/definitions/positive_integer" }
                }
              },
              "nextDate" : {
                "$ref" : "../defs.json#/definitions/nonempty_string",
                "format" : "date-time"
              }
            }
          }
        }
      }
    }
  }
}

В intellij результатом является следующее: (каждое показанное свойство не должно быть действительным, однако некоторые просто игнорируются и допускаются (как отрицательныечисла и нули и т. д.) Я не получаю предупреждений / ошибок о невозможности разрешения $ ref. Автозаполнение даже завершает относительное имя файла и свойство определения для меня.

pic1


edit

Еще поиграв с ним, я обнаружил, что он связан с относительными URL-адресами. Например, в моем pii (информация, идентифицирующая личность)) папка, в которой расположена схема заданий, если я переместлю эту схему в корневой каталог с другими схемами, все будет проверено правильно. Для иллюстрации нового дерева проекта:

-------------------------------------------
| C:/project                              |
| `----main.json (file to be validated)   |
| `----/schemas                           |
|   `----base.json                        |
|   `----datatypes.json                   |
|   `----defs.json                        |
|   `----frequent.json                    |
|   `----jobs.json                        |
-------------------------------------------

pic2

Для краткости моя схема фактически не хранится в http://project.com. BaНасколько я понимаю, $id это не имеет значения, это просто способ для схем общаться друг с другом.Я хотел бы максимально упростить модульную структуру и разделить схемы на собственные подпапки (например, pii), но в моем примере это не проверяется.

1 Ответ

1 голос
/ 27 мая 2019

Похоже, что вы были на правильном пути, однако вы не можете использовать $ref с другими ключевыми словами в том же объекте, поскольку они всегда игнорируются при использовании $ref с JS-схемой draft-7.

8.3.Ссылки на схему с помощью «$ ref»

Ключевое слово «ref» используется для ссылки на схему и предоставляет возможность проверять рекурсивные структуры с помощью самоссылки.

Схема объекта сСвойство "$ ref" ДОЛЖНО интерпретироваться как ссылка
"$ ref".Значение свойства "$ ref" ДОЛЖНО быть URI
Ссылка.Разрешенный к текущей базе URI, он идентифицирует
URI используемой схемы.НЕОБХОДИМО игнорировать все остальные свойства в объекте "$ ref".

https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8.3

Если вы хотите использовать $ref с другими ключевыми словами в том же объекте схемы, выВместо этого нужно создать два объекта схемы и обернуть их в allOf.

...