Установка дополнительных свойств на основе других значений свойств в схеме JSON - PullRequest
0 голосов
/ 06 апреля 2020

Я хочу установить некоторые свойства элемента фильтра на основе значения существующего свойства. Если свойство Type имеет значение Range, то свойства From и To должны быть добавлены в filterItem. В противном случае остальные свойства должны быть массивом FilterValues. Я попытался установить свойства с помощью if и else, но мне кажется, что мне чего-то не хватает.

Части моей JSON схемы:

"Filter": {
              "type": [
                "array",
                "null"
              ],
              "items": {
                "$ref": "#/definitions/filterItem"
              },
              "additionalProperties": false
            }
___________________________________________________

"filterItem": {
      "type": "object",
      "properties": {
        "AttributeCode": {
          "type": "string",
          "pattern": "^[a-z0-9_-]+$"
        },
        "Typ": {
          "type": "string"
        },
        "if": {
          "properties": {
            "Typ": {
              "const": "Range"
            }
          }
        },
        "then": {
          "properties": {
            "From": {
              "type": "integer",
              "minLength": 1
            },
            "To": {
              "type": "integer",
              "minLength": 1
            }
          },
          "additionalProperties": false
        },
        "else": {
          "properties": {
            "FilterValues": {
              "type": "array",
              "items": {
                "type": "string",
                "pattern": "^[a-z0-9_-]+$"
              }
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }

Валидатор показывает, что свойства не соответствуют моей схеме (снимок экрана): validator

1 Ответ

0 голосов
/ 07 апреля 2020

У вашей схемы есть две основные проблемы: как вы используете if - then - else и как вы используете addtionalProperties.

if - then - else

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

"properties": {
  "foo": { ... }
  "if": { ... },
  "then": { ... }
}

Это не определяет одно свойство, "foo", плюс условное. Он определяет три свойства: «foo», «if», «then». Вам нужно довести условный уровень до уровня, чтобы он был распознан валидатором.

"properties": {
  "foo": { ... }
},
"if": { ... }
"then": { ... }

В противном случае вы правильно используете if - then - else. Это просто не в том месте.

additionalProperties

Как только вы получите if - then - else в нужном месте, вы заметите, что вы получаете куча additionalProperties ошибок. additionalProperties может учитывать только ключевые слова properties и patternProperties в одном и том же месте схемы.

{
  "allOf": [
    {
      "properties": {
        "foo": { ... }
      }
    },
    {
      "properties": {
        "bar": { ... }
      },
      "additionalProperties": false
    }
  ]
}

/allOf/1/additionalProperties может учитывать только /allOf/1/properties, а не /allOf/0/properties , Таким образом, { "foo": 1, "bar": 2 } будет недействительным, потому что "foo" не определено в /allOf/1/properties.

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

Чтобы эффективно использовать additionalProperties, вам нужны все возможные имена свойств под одним и тем же ключевым словом properties.

"properties": {
  "foo": { ... },
  "bar": { ... }
},
"required": ["foo"],
"additionalProperties": false,
"if": {
  "properties": {
    "foo": { "const": 1 }
  },
  "required": ["foo"]
},
"then": { "required": ["bar"] }

Это один из возможных подходов. «bar» ожидается только в том случае, если «foo» равен 1, но «bar» определен в верхней части и требуется только в случае выполнения условия. Это не только заставляет additionalProperties работать так, как вы ожидаете, его также легче читать, потому что все определения свойств находятся в одном месте, а условные схемы минимальны.

В этот момент вы можете быть обеспокоены тем, что включение «bar», когда «foo» не равно 1, не выдает ошибку. Опять же, я бы посоветовал вам игнорировать дополнительное свойство, а не запрещать его, если ваш домен позволяет. Но, если вам действительно нужно, вы можете использовать else, чтобы запретить дополнительное поле.

"else": { "not": { "required": ["bar"] } }

Будьте осторожны, чтобы не перепутать слова в этой схеме. Это не означает «не требуется», что звучит как «необязательный», это означает «запрещено».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...