Схема JSON: Могу ли я использовать глубже, чем корень схемы?

Я хочу проверить такие объекты

{
  type: "user",
  data: {id: 1},
}

а также

{
  type: "account",
  data: {uuid: "xxxx"},
}

Я думал, что могу написать такую ​​схему

{
  type: "object",
  properties: {
    type: {enum: ["user", "account"]},
    data: {
      "if": {properties: {type: {const: "user"}}},
      "then": {
        type: "object",
        properties: {
          id: {type: "number"}
        }
      },
      "else": {
        type: "object",
        properties: {
          uuid: {type: "string"}
        }
      },
    }
  }
}

но похоже, что я не могу сослаться на корневое поле type из контекста поля data. Итак, у меня есть два вопроса. Могу ли я использовать if глубже root? Если я могу, то как ссылаться на родительский или корневой объект из вложенного объекта? Я использую узел ajv для проверки.


person redexp    schedule 17.07.2020    source источник


Ответы (1)


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

Первое, что происходит при обработке схемы JSON, - это то, что схема в целом применяется к экземпляру в целом.

properties - это ключевое слово аппликатора, поскольку оно само по себе не утверждает никаких правил проверки. ЗНАЧЕНИЯ объекта properties - это подсхемы (которые сами по себе являются схемами), которые ПРИМЕНЯЮТСЯ к значению местоположения экземпляра, когда соответствующий КЛЮЧ совпадает.

Чтобы дать вам пример, в вашей схеме подсхема в properties > type применяется к местоположению экземпляра type, что означает ЗНАЧЕНИЕ ключа объекта type. Если type не существует в ваших данных, подсхема в вашей схеме ничего не сделает (она не будет применяться нигде).

В широком смысле это модель обработки схемы по отношению к экземпляру. Надеюсь, это объясняет, почему вы не можете работать так, как ожидаете. Однако все еще возможно добиться того, чего вы хотите.

then и else являются ключевыми словами условного аппликатора, поэтому их нужно применять по одной и той же модели.

Что вам нужно сделать, так это использовать if, then, else на верхнем уровне, но иметь глубокое / вложенное приложение проверки, которую вы хотите выполнить.

Вот демонстрация новой схемы и экземпляра https://jsonschema.dev/s/sejHF

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "properties": {
    "type": {
      "enum": [
        "user",
        "account"
      ]
    },
    "data": {}
  },
  "if": {
    "properties": {
      "type": {
        "const": "user"
      }
    }
  },
  "then": {
    "type": "object",
    "properties": {
      "data": {
        "properties": {
          "id": {
            "type": "number"
          }
        }
      }
    }
  },
  "else": {
    "type": "object",
    "properties": {
      "data": {
        "properties": {
          "uuid": {
            "type": "string"
          }
        }
      }
    }
  }
}

Если вы также хотите убедиться, что id присутствует, когда type равно user, вам также необходимо добавить required: ['id'] в подсхему then. (Вам нужно будет сделать то же самое в предложении else, если вы хотите также проверить uuid.

person Relequestual    schedule 18.07.2020