Проверка схемы Json: зависимости от подсхемы - PullRequest
0 голосов
/ 15 ноября 2018

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

Ниже моя текущая схема и пример json. Мне нужно, чтобы оно говорило, что если «SW Large» существует и значение истинно, то для этого требуется, чтобы «SW Words» существовало в пределах объекта Register

"anyOf", которое я использовал в схеме ниже, было моей попыткой.

Работает, чтобы сказать, если "SW Large" имеет значение true, тогда "SW Words" требуется, иначе нет, но если поле "SW Large" отсутствует, оно все равно будет настаивать на том, что "SW Words" требуется.

Как я могу изменить «anyOf» и «allOf», чтобы проверить, действительно ли существует «SW Large»?

Редактировать: Снижение JSON, чтобы быть немного более управляемым

Схема:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "Registers"
  ],
  "properties": {
    "Registers": {
      "$id": "#/properties/Registers",
      "type": "array",
      "items": {
        "$id": "#/properties/Registers/items",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "Name",
          "Address",
          "Fields"
        ],
        "anyOf": [
          {
            "allOf": [
              { "not": { "properties": { "Fields" : { "items": { "properties": { "SW Large": { "const": true } } } } } } }
            ]
          },
          {
            "required": ["SW Words"]
          }
        ],
        "properties": {
          "Name": {
            "$id": "#/properties/Registers/items/properties/Name",
            "type": "string"
          },
          "Address": {
            "$id": "#/properties/Registers/items/properties/Address",
            "type": "string"
          },
          "SW Words": {
            "$id": "#/properties/Sections/items/properties/Blocks/items/properties/SW Words",
            "type": "integer",
            "default": 2,
            "minimum": 2
          },
          "Fields": {
            "$id": "#/properties/properties/Registers/items/properties/Fields",
            "type": "array",
            "items": {
              "$id": "#/properties/Registers/items/properties/Fields/items",
              "type": "object",
              "additionalProperties": false,
              "required": [
                "Name"
              ],
              "properties": {
                "Name": {
                  "$id": "#/properties/Registers/items/properties/Fields/items/properties/Name",
                  "type": "string"
                },
                "SW Large": {
                  "$id": "#/properties/Registers/items/properties/Fields/items/properties/SW Large",
                  "type": "boolean"
                }
              }
            }
          }
        }
      }
    }
  }
}

Пример Json

{
  "Registers": [
    {
      "Name": "device",
      "Address": "100",
      "SW Words": 2,
      "Fields": [
        {
          "Name" : "Product",
          "SW Large" : true
        },
        {
          "Name": "Version"
        }
      ]
    }
  ]
}

1 Ответ

0 голосов
/ 15 ноября 2018

Юк, восходящие зависимости могут быть действительно неприятными. Модель должна иметь такую ​​форму?

Решение

Вы на правильном пути. Чего вам не хватает, так это правильной проверки, если хотя бы один элемент массива «Поля» имеет «SW Large»: true , а затем формирует правильную зависимость.

Начиная с черновика-06, она решается с помощью ключевого слова "содержит". Чтобы не повторять содержание, рекомендую прочитать следующее:

Схема JSON: Как проверить, что массив содержит хотя бы один объект со свойством с заданным значением?

Схема Json: Требовать свойство только в том случае, если в глубоко вложенном объекте присутствует конкретное свойство (очень познавательно!)

https://json -schema.org / понимание-json-схема / ссылка / массив.html

Ваша схема переработана ниже. Смотрите раздел "определения"

Прежде всего, добавляется «содержит»: { схема } к определению «Поля» . Мне нужно это как отдельную схему, чтобы использовать ее в качестве условия в логической импликации.

"definitions" : {
    "Fields-contains-at-least-1-element-with-SW-Large-true" : {
      "properties": { 
        "Fields" : {
          "contains" : {
            "properties": { 
              "SW Large": { "enum": [true] } 
            },
            "required" : ["SW Large"]
          }
        } 
      },
    }
  },

Если вы добавите его навсегда, оно может выглядеть следующим образом:

"Fields" : {
  "type" : "array",
  "contains" : {
    "properties": { 
      "SW Large": { "enum": [true] } 
    },
    "required" : ["SW Large"]
  }
  "items": {...},
}

, что переводится как "хотя бы один элемент из " Поля " должен содержать объект с указанным именем свойства и указанным значением". Каждый JSON с массивом "Fields" , который не содержит элементов с "SW Large": true , не пройдет проверку такой схемы. И если вы перевернете «содержит» определение схемы , например:

"Fields" : {
    "type" : "array",
    "contains" : {
      "not" : {
        "properties": { 
          "SW Large": { "enum": [true] } 
        },
        "required" : ["SW Large"]
      }
    }
    "items": {...},
  }

это будет означать "никакой элемент из " Поля " массив может содержать объект с указанным именем свойства и указанным значением". Каждый JSON с массивом «Поля» , который содержит хотя бы один элемент с «SW Large»: true , не прошел бы проверку для такой схемы.

Я не хочу, чтобы что-либо из вышеперечисленного произошло. Я хочу связать условие "Поля / содержит" с требованием или не требовать свойства "SW Words" на уровень выше, отсюда исключение схемы из раздела "определения" и создание правильного использовать его.

"восходящая зависимость" определяется с помощью этой проверки и правильного логического значения с ключевым словом "anyOf"

Не содержит хотя бы 1 элемент с «SW Large»: true ИЛИ «SW Words» требуется

"definitions" : {
    "upward-dependency" : {
      "anyOf" : [
        { "not" : {"$ref" : "#/definitions/Fields-contains-at-least-1-element-with-SW-Large-true"} },
        { "required" : ["SW Words"] }
      ]
    },
  },

На уровне отдельного элемента массива «Registers» я добавил «зависимости». Всякий раз, когда элемент «Поля» появляется в одном из элементов «Регистров», проверяется, содержит ли он неудачный «SW Large»: true , и если он появляется - «Слова SW» становятся обязательными. Voila!

       "items" : {
        "$id": "#/properties/Registers/items
        "type" : "object",
        "properties" : {
          "Fields": {
            "$id": "#/properties/Registers/items/properties/Fields",
            "type": "array",
            "items": {
              "$id": "#/properties/Registers/items/properties/Fields/items",
              "type": "object",
              "propertyNames" : {
                "enum" : [
                  "Name",
                  "SW Large"
                ]                
              },
              "required": [
                "Name"
              ],
              "properties": {
                "Name": {
                  "$id": "#/properties/Registers/items/properties/Fields/items/properties/Name",
                  "type": "string"
                },
                "SW Large": {
                  "$id": "#/properties/Registers/items/properties/Fields/items/properties/SW Large",
                  "type": "boolean"
                }
              }
            }
          }
        },
        "dependencies" : {
          "Fields" : { "$ref" : "#/definitions/upward-dependency" }
        },
      }

Я проверил схему с помощью онлайн-валидатора и добавил ваш объект в раздел "примеры".

Полная схема:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "propertyNames" : {
    "enum" : [
      "Registers"
    ]
  },
  "required": [
    "Registers"
  ],
  "examples" : [
    {
      "Registers": [
        {
          "Name": "device",
          "Address": "100",
          "SW Words": 2,
          "Fields": [
            {
              "Name" : "Product",
              "SW Large" : true
            },
            {
              "Name": "Version"
            }
          ]
        }
      ]
    }
  ],
  "properties": {
    "Registers": {
      "$id": "#/properties/Registers",
      "type": "array",
      "items": {
        "$id": "#/properties/Registers/items",
        "type": "object",
        "propertyNames" : {
          "enum" : [
            "Name",
            "Address",
            "SW Words",
            "Fields"
          ]
        },
        "required": [
          "Name",
          "Address",
          "Fields"
        ],
        "properties": {
          "Name": {
            "$id": "#/properties/Registers/items/properties/Name",
            "type": "string"
          },
          "Address": {
            "$id": "#/properties/Registers/items/properties/Address",
            "type": "string"
          },
          "SW Words": {
            "$id": "#/properties/Sections/items/properties/Blocks/items/properties/SW Words",
            "type": "integer",
            "default": 2,
            "minimum": 2
          },
          "Fields": {
            "$id": "#/properties/Registers/items/properties/Fields",
            "type": "array",
            "items": {
              "$id": "#/properties/Registers/items/properties/Fields/items",
              "type": "object",
              "propertyNames" : {
                "enum" : [
                  "Name",
                  "SW Large"
                ]                
              },
              "required": [
                "Name"
              ],
              "properties": {
                "Name": {
                  "type": "string"
                },
                "SW Large": {
                  "type": "boolean"
                }
              }
            }
          }
        },
        "dependencies" : {
          "Fields" : { "$ref" : "#/definitions/upward-dependency" }
        },
      }
    }
  },
  "definitions" : {
    "upward-dependency" : {
      "anyOf" : [
        { "not" : {"$ref" : "#/definitions/Fields-contains-at-least-1-element-with-SW-Large-true"} },
        { "required" : ["SW Words"] }
      ]
    },
    "Fields-contains-at-least-1-element-with-SW-Large-true" : {
      "properties": { 
        "Fields" : {
          "contains" : {
            "properties": { 
              "SW Large": { "enum": [true] } 
            },
            "required" : ["SW Large"]
          }
        } 
      },
    }
  },
}

Некоторые примечания:

Вместо "AdditionalProperties": false , пожалуйста, используйте "propertyNames". Он был специально введен с целью убедиться, что в схеме aginst, проверенной объектом JSON, присутствуют только требуемые свойства.

"propertyNames" : {
    "enum" : [
      "Registers"
    ]
  }

См .: https://json -schema.org / понимание-json-схема / reference / object.html # property-names

Очень важно правильно формировать схемы / подсхемы в зависимости от того, на каком уровне они должны применяться. Обратите внимание, как "# / Definitions / Fields-contains-at-минимум-1-element-with-SW-Large-true" правильно отражает схему в "# / Registers / items" уровень вложенности (поскольку «зависимости» применяются к объекту на "# / Registers / items" уровне, и его можно рассматривать как "" / / Registers / items / dependencies " ). См. https://json -schema.org / понимание-json-схема / ссылка / object.html # зависимости .

Если вы намереваетесь проверить отдельный элемент массива "Поля" отдельно или даже отдельный элемент массива "Регистры" по отдельности, вы можете рассмотреть возможность преобразования схемы в отдельные подсхемы как я сделал с "questionA" здесь: https://stackoverflow.com/a/53309856/2811843. Таким образом - если есть необходимость - вы можете легко исключить подсхемы из основной схемы и просто правильно ссылаться на них, используя ключевое слово "$ ref" . Некоторое чтение JSON Pointer и относительного JSON Pointer также может быть полезно для структурирования сложных схем.

Стоит начать с: https://json -schema.org / понимание-json-схема / structuring.html

Надеюсь, это помогло.

...