Как использовать anyOf для разных типов свойств? - PullRequest
3 голосов
/ 22 апреля 2020

В приведенной ниже схеме мне нужны items_list, price и variance в качестве необходимых ключей. Условие price и variance может быть или не быть нулевым, но оба не могут быть нулевыми.

Хотя я могу этого достичь, я с нетерпением жду, если есть более короткий способ сделать это. Кроме того, я не уверен, где именно поставить ключи required и additionalProperties.

Любая помощь приветствуется.

{
    "type": "object",
    "properties": {
        "items_list": {
            "type": "array",
            "items": {
                "type": "string"
            }
        },
    },
    "anyOf": [
        {
            "properties": {
                "price": {
                    "type": "number",
                    "minimum": 0,
                },
                "variance": {
                    "type": [
                        "number",
                        "null"
                    ],
                    "minimum": 0,
                },
            },
        },
        {
            "properties": {
                "price": {
                    "type": [
                        "number",
                        "null"
                    ],
                    "minimum": 0,
                },
                "variance": {
                    "type": "number",
                    "minimum": 0,
                },
            },
        },
    ],
    # "required": [
    #     "items_list",
    #     "price",
    #     "variance",
    # ],
    # "additionalProperties": False,
}

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

Чтобы ответить на вопрос «это может быть короче?», Ответ - да. Общее правило: никогда не определять что-либо в булевых логах c ключевых слов. Используйте ключевые слова логической логики c только для добавления составных ограничений. Я использую термин «составное ограничение» для обозначения ограничения, основанного на более чем одном значении в схеме. В этом случае сложное ограничение заключается в том, что цена и дисперсия не могут быть равны нулю.

{
  "type": "object",
  "properties": {
    "items_list": {
      "type": "array",
      "items": { "type": "string" }
    },
    "price": { "type": ["number", "null"], "minimum": 0 },
    "variance": { "type": ["number", "null" ], "minimum": 0 }
  },
  "required": ["items_list", "price", "variance"],
  "additionalProperties": false,
  "allOf": [{ "$ref": "#/definitions/both-price-and-variance-cannot-be-null" }],
  "definitions": {
    "both-price-and-variance-cannot-be-null": {
      "not": {
        "properties": {
          "price": { "type": "null" },
          "variance": { "type": "null" }
        },
        "required": ["price", "variance"]
      }
    }
  }
}

Мало того, что вам не нужно прыгать через обручи, чтобы additionalProperties работал должным образом, также легче читать. Это даже соответствует вашему описанию проблемы: «цена и дисперсия могут быть или не быть нулевыми» (properties), но «оба не могут быть нулевыми» (not (составное ограничение)). Вы могли бы сделать это еще короче, вставив определение, но я включил его, чтобы показать, насколько выразительным может быть этот прием, все еще будучи короче, чем исходная схема.

2 голосов
/ 22 апреля 2020

Похоже, вы в основном правы. Это правильное место для размещения required.

Используя additionalProperties: false, вам также нужно определить properties на верхнем уровне, additionalProperties не может "видеть сквозь" *Of ключевые слова (аппликаторы).

Вы можете добавить properties: [prop] : true, но определите все свойства. Это необходимо сделать, потому что additionalProperties знает только о properties в одном и том же объекте схемы на том же уровне.

...