атрибут jsonSchema умовно необхідний


97

У jsonSchema ви можете вказати, чи визначені поля є обов'язковими, чи не використовуючи requiredатрибут:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "header": {
            "type": "object",
            "properties": {
                "messageName": {
                    "type": "string"
                },
                "messageVersion": {
                    "type": "string"
                }
            },
            "required": [
                "messageName",
                "messageVersion"
            ]
        }
    },
    "required": [
        "header"
    ]
}

У певних випадках я хотів би, щоб messageVersionполе не було обов’язковим. Чи є спосіб зробити умовою обов'язковість цього поля умовою?


Так, це повинно бути можливим. Яка інформація в даних може викликати обов’язковість?
jruizaranguren

@SarveswaranMeenakshiSundaram - я не знаю, що використовував лише v4 схеми json
tom redfern,

Чи можливо це взагалі у версії 3?
Сарвеш,

@SarveswaranMeenakshiSundaram - я не знаю. Спробуйте і дайте нам знати, будь ласка!
Том Редферн,

Відповіді:


264

Залежно від вашої ситуації існує кілька різних підходів. Я можу придумати чотири різні способи умовно вимагати поля.

Залежності

dependenciesКлючовим словом є умовним зміною requiredключового слова. Властивість Foreach у dependencies, якщо властивість присутня в JSON, що перевіряється, тоді схема, пов'язана з цим ключем, також повинна бути дійсною. Якщо властивість "foo" присутня, тоді властивість "bar" є обов’язковою

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": { "required": ["bar"] }
  }
}

Існує також коротка форма, якщо схема містить лише requiredключове слово.

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": ["bar"]
  }
}

Наслідування

Якщо ваш стан залежить від значення поля, ви можете використовувати булеву логічну концепцію, яка називається імплікацією. "A означає B" фактично означає, що якщо A є істинним, то B також має бути істинним. Наслідок також може бути виражений як "! A або B". Або властивість "foo" не дорівнює "bar", або властивість "bar" є обов'язковою . Або, іншими словами: Якщо властивість "foo" дорівнює "bar", тоді необхідна властивість "bar"

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "anyOf": [
    {
      "not": {
        "properties": {
          "foo": { "const": "bar" }
        },
        "required": ["foo"]
      }
    },
    { "required": ["bar"] }
  ]
}

Якщо "foo" не дорівнює "bar", #/anyOf/0збіги та перевірка успішні. Якщо "foo" дорівнює "бар", #/anyOf/0не вдається і #/anyOf/1повинен бути дійсним дляanyOf успішної перевірки.

Перелік

Якщо ваш умовний заснований на перерахуванні, це трохи більш прямо. "foo" може бути "bar" або "baz". Якщо "foo" дорівнює "bar", тоді потрібно "bar". Якщо "foo" дорівнює "baz", тоді потрібно "baz".

{
  "type": "object",
  "properties": {
    "foo": { "enum": ["bar", "baz"] },
    "bar": { "type": "string" },
    "baz": { "type": "string" }
  },
  "anyOf": [
    {
      "properties": {
        "foo": { "const": "bar" }
      },
      "required": ["bar"]
    },
    {
      "properties": {
        "foo": { "const": "baz" }
      },
      "required": ["baz"]
    }
  ]
}

Якщо-то-інше

Щодо нове доповнення до JSON Schema (проект-07) додає if, thenі elseключові слова. Якщо властивість "foo" дорівнює "bar", тоді властивість "bar" є обов'язковою

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "if": {
    "properties": {
      "foo": { "const": "bar" }
    },
    "required": ["foo"]
  },
  "then": { "required": ["bar"] }
}

РЕДАГУВАТИ 23.12.2017: Розділ "Наслідки" оновлено та додано розділ "Якщо потім".

РЕДАГУВАТИ 06.04.2018: Виправлення для If-Then-Else та оновлення одиночних enums для використання const.


7
@scubbo Я не шанувальник if-then-elseключових слів, і я відмовляюся їх використовувати. Але, якщо ви вирішите використовувати його, я пропоную завжди обертати їх у allOfте, що містить лише ці три ключові слова. { ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
Джейсон Дерозьє

2
@Jason Чому не фанат if...? Думаю, коротка думка щодо цього у вашій відповіді була б цілком виправданою. Або це довга історія?
Глиняні мости

6
@ClayBridges Розділ коментарів не є правильним місцем для цієї дискусії, але ось коротка версія. Як правило, ключові слова схеми JSON не містять громадянства. Інша інформація, крім значення ключового слова, не може використовуватися для перевірки екземпляра. if, thenІ elseпорушувати це правило , тому що вони залежать один від одного.
Джейсон Дерозьє

3
@GGirard, це найкращий спосіб використання цих шаблонів у схемі JSON, який мені відомий. Булеві операції офіційно задокументовані, а решта - це просто математика. allOf== І, anyOf== АБО, oneOf== XOR і not== НЕ. Ви можете погуглити "булеву алгебру", щоб отримати більше ресурсів з математики (наприклад, імплікація).
Джейсон Дерозьє

2
@AlexeyShrub Я давно хотів написати про це, але мене відволікали інші речі. Я прихильник ідеї умовного. Це полегшує розуміння людьми. Я заперечую проти того, як це було визначено як три окремі ключові слова, що містять статус (див. Попередній коментар). Наявність ключових слів, які порушують архітектурні властивості, за якими слідують інші ключові слова, робить валідатори схеми JSON важче впровадженими та менш ефективними. Якби умовні умови визначались по-іншому, без громадянства, тоді я не мав би заперечень.
Джейсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.