Вложение oneOf в anyOf для JSON-схемы - PullRequest
2 голосов
/ 30 сентября 2019

Вот схема JSON и JSON, как показано ниже в ссылке для целей иллюстрации.

Схема JSON и JSON

Формат: отдельный объект JSON(с их дополнительными атрибутами и может варьироваться в зависимости от другого объекта в массиве) внутри массива может быть любой 3 региона: «Америка», «Азия» и «Европа» и, по крайней мере, тип объекта региона должен быть там. Это может быть достигнуто с помощью свойства minItems для массива)

Постановка задачи:

  1. Отдельный объект JSON в массиве может относиться к любому 3 регионам: «америка», «азия»и 'europe' и, по крайней мере, тип объекта региона должен быть там

    ==> Я могу решить эту проблему, поместив все объекты региона в массив anyOf, как я хочу, чтобы они соответствовали по крайней мереодин из допустимых объектов региона.

  2. Либо объект JSON 'asia' или 'europe' может существовать вместе с другим типом региона. Оба не могут сосуществовать.

    ==> Я пытался использовать 'oneOf', но он прошел проверку ajv. На самом деле это должно провалиться. Может кто-нибудь помочь. Спасибо

JSON-схема

{
    "type": "object",
    "properties": {
        "stat_data": {
            "type": "array",
            "minItems": 1,
            "items": {
                "type": "object",
                "properties": {},
                "anyOf": [{
                        "required": ["region"],
                        "properties": {
                            "region": {
                                "enum": ["america"]
                            },
                            "country": {
                                "type": "string"
                            },
                            "population": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "oneOf": [
                            {
                                "required": ["region"],
                                "properties": {
                                    "region": {
                                        "enum": ["asia"]
                                    },
                                    "country": {
                                        "type": "string"
                                    },
                                    "details": {
                                        "type": "object",
                                        "properties": {
                                            "language": {
                                                "type": "string"
                                            },
                                            "tz": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            }, {
                                "required": ["region"],
                                "properties": {
                                    "region": {
                                        "enum": ["europe"]
                                    },
                                    "country": {
                                        "type": "string"
                                    },
                                    "language": {
                                        "type": "string"
                                    }
                                }
                            }
                        ]
                    }
                ]
            }
        }
    }
}

JSON Объект FAIL, поскольку объекты типа "asia" и "europe" не могут сосуществовать.

{
    "stat_data": [{
            "region": "america",
            "country": "USA",
            "states": "50"
        }, {
            "region": "asia",
            "country": "Japan",
            "details": {
                "language": "Japanese",
                "tz": "utc+9.00"
            }
        }, {
            "region": "europe",
            "country": "finland",
            "language": "Finnish"
        }
    ]
}

JSON Object to PASS, поскольку существует ТОЛЬКО объект типа "asia".

{
    "stat_data": [{
            "region": "america",
            "country": "USA",
            "states": "50"
        }, {
            "region": "asia",
            "country": "Japan",
            "details": {
                "language": "Japanese",
                "tz": "utc+9.00"
            }
        }
    ]
}

JSON Object to PASS как ТОЛЬКО объект типа "europe" существует.

{
    "stat_data": [{
            "region": "america",
            "country": "USA",
            "states": "50"
        }, {
            "region": "europe",
            "country": "finland",
            "language": "Finnish"
        }
    ]
}

1 Ответ

1 голос
/ 01 октября 2019

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

Помните, items применяет схему значений к КАЖДОМУ элементу в массиве. Он не выражает никаких ограничений на весь массив в целом. contains проверяет, что по крайней мере один из элементов в массиве проверяется по его схеме значений.

То, что вы хотите сказать, может иметь каждый элемент в массиве america или europe или asia, но массив может не содержать europe, если он содержит asia, и обратное.

Я произвел рефакторинг схемы и внес некоторые изменения.

Надеюсь, вы также можете увидетьцель ясна при использовании oneOf >> (contains и not> contains).

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

Схема JSON и демонстрация проверки данных

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "containtsAsia": {
      "contains": {
        "properties": {
          "region": {
            "const": "asia"
          }
        }
      }
    },
    "containsEurope": {
      "contains": {
        "properties": {
          "region": {
            "const": "europe"
          }
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "stat_data": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "properties": {
          "region": {
            "enum": [
              "america",
              "asia",
              "europe"
            ]
          },
          "country": {
            "type": "string"
          },
          "population": {
            "type": "string"
          }
        }
      },
      "oneOf": [
        {
          "allOf": [
            {
              "$ref": "#/definitions/containtsAsia"
            },
            {
              "not": {
                "$ref": "#/definitions/containsEurope"
              }
            }
          ]
        },
        {
          "allOf": [
            {
              "$ref": "#/definitions/containsEurope"
            },
            {
              "not": {
                "$ref": "#/definitions/containtsAsia"
              }
            }
          ]
        }
      ]
    }
  }
}
...