Как установить тип объекта схемы на основе значения другого свойства? - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть объект (от третьего лица, поэтому я не могу его изменить), который имеет свойство с именем «ключ», а другое свойство с именем «значение» является необязательным, и его тип зависит от значениясвойство "key".

Например:
Если ключом является "комментарий", тип значения {"Text":"commentValue"}.
Если ключом является "смещение", типом значения является {"seconds":int}.
Если ключом является «погода», типом значения является {"value": Enum["sun", "clouds", "rain"...]}

Кроме того, некоторые ключи не имеют свойства значения, поэтому схема должна запрещать его появление сэти ключи.один из этих ключей находится в режиме ожидания (как вы можете видеть в моей текущей попытке ниже)

Я пытался манипулировать примерами кода из этого SO ответа , но не смог сделать эторабота.

В настоящее время я пытаюсь проверить вывод json по моим попыткам схемы, используя JSON Schema Validator от Newtonsoft , но мне не удается правильно определить свойство "value".

Это мой код:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "TestOptionalObject",
    "type": "object",
    "additionalProperties": false,
    "required": [
        "test"
    ],
    "properties": {
        "test": {
            "$ref": "#/definitions/test"
        }
    },
    "definitions": {
        "test": {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "key",
            ],
            "properties": {
                "key": {
                    "type": "string",
                    "enum": ["standby", "comment", "offset"]
                },
                "value" : {
                    "if": {
                        "properties": {
                          "key": {"enum": ["comment"]}
                        }
                    },
                    "then": { 
                        "$ref": "#/definitions/commentValue"
                    },
                    "if": {
                        "properties": {
                          "key": {"enum": ["offset"]}
                        }
                    },
                    "then": { 
                        "$ref": "#/definitions/offsetValue"
                    }
                }
            }
        },
        "commentValue" : {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "text",
            ],
            "properties": {
                "text" : {"type" : "string"}
            }
        },
        "offsetValue" : {
            "type": "object",
            "additionalProperties": false,
            "required": [
                "seconds",
            ],
            "properties": {
                "seconds" : {
                    "type": "integer",
                    "format": "int32"
                }
            }
        }
    }
}

И вот сообщения об ошибках, которые я получаю:

JSON не соответствует схеме из 'then'.Путь к схеме: # / definitions / offsetValue / then

Свойство 'text' не определено, и схема не допускает дополнительных свойств.Путь к схеме: # / definitions / offsetValue / AdditionalProperties

В объекте: секунд отсутствуют обязательные свойства.Путь к схеме: # / definitions / offsetValue / обязательный

Примеры Json для проверки:

В случае ошибки:

{
  "test": {
    "key": "comment",
      "value": {"seconds":12}
  }
}


{
  "test": {
    "key": "standby",
     "value": {"asdf":12}
  }
}

В случае передачи:

{
  "test": {
    "key": "comment",
     "value": {"text":"comment text"}
  }
}


{
  "test": {
    "key": "offset",
     "value": {"seconds":12}
  }
}

1 Ответ

0 голосов
/ 21 декабря 2018

Я изменил вашу схему JSON так, чтобы она выполняла то, что вы ожидаете, за исключением ключа формы standby, поскольку вы не включили его в свою схему, и вы сможете скопировать созданный мной шаблон, чтобы добавить новыйключи по мере необходимости.

Основной проблемой, с которой вы столкнулись, было ложное предположение о том, где разместить if/then/else ключевые слова.Это ключевые слова аппликатора, поэтому они должны применяться к объекту, состояние которого вы проверяете, а не к значению ключа properties.Поскольку вы использовали if/then/else в объекте со значением value, вы применяли if/then/else к значению value, а не test.

Вы нуждались в вашем ifприменить к test, чтобы получить правильную область для проверки значения свойства key.

Вот результирующая фиксированная схема:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "TestOptionalObject",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "test"
  ],
  "properties": {
    "test": {
      "$ref": "#/definitions/test"
    }
  },
  "definitions": {
    "test": {
      "type": "object",
      "required": [
        "key"
      ],
      "properties": {
        "key": {
          "type": "string",
          "enum": [
            "standby",
            "comment",
            "offset"
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "key": {
                "const": "comment"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "$ref": "#/definitions/commentValue"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "key": {
                "const": "offset"
              }
            }
          },
          "then": {
            "properties": {
              "value": {
                "$ref": "#/definitions/offsetValue"
              }
            }
          }
        }
      ]
    },
    "commentValue": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string"
        }
      }
    },
    "offsetValue": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "seconds"
      ],
      "properties": {
        "seconds": {
          "type": "integer",
          "format": "int32"
        }
      }
    }
  }
}

Если вам нужна дополнительная помощь, пожалуйста,не стесняйтесь присоединиться к JSON Schema slack, используя ссылку для обсуждения на сайте http://json -schema.org .

...