Как объявить зависимости вложенных свойств?

Я использую Draft-04 схемы JSON. Можно ли установить зависимости на основе существования подсвойства и/или зависимости от подсвойства? Или я вынужден использовать allOf для управления такими зависимостями?

У меня есть следующее (вы можете поиграть с ним на https://repl.it/@neverendingqs/JsonSchemaNestedDependencies):

'use strict';

const Ajv = require('ajv');
const assert = require('chai').assert;

// Using [email protected]
const draft4 = require('ajv/lib/refs/json-schema-draft-04.json');

const schema = {
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "foo1": {
      "type": [ "object" ],
      "properties": {
        "bar1": { "type": "string" }
      }
    },
    "foo2": {
      "type": [ "object" ],
      "properties": {
        "bar2": { "type": "string" }
      }
    }
  },
  "dependencies": {
    "foo1": ["foo2"],

    // Is this possible?
    "foo1/bar1": ["foo2/bar2"]
  }
};

const schemaName = 'my-schema';

const ajv = new Ajv();
ajv.addMetaSchema(draft4);
ajv.addSchema(schema, schemaName);


assert.isTrue(
  ajv.validate(schemaName, {
    "foo1": { "bar1": "a" },
    "foo2": { "bar2": "c" }
  }),
  ajv.errorsText(ajv.errors, { dataVar: 'event' })
);

assert.isFalse(ajv.validate(schemaName, {
  "foo1": { "bar1": "a" }
}));

// Looking to cause this to pass
assert.isFalse(ajv.validate(schemaName, {
  "foo1": { "bar1": "a" },
  "foo2": {}
}));

Я ищу ответы на проект 04, но меня также интересуют ответы с использованием более поздних спецификаций.

EDIT: Draft-04 относится к спецификациям в разделе http://json-schema.org/specification-links.html#draft-4. В частности, я использую dependencies, который определен в спецификации Validation (https://tools.ietf.org/html/draft-fge-json-schema-validation-00)


person neverendingqs    schedule 14.03.2018    source источник


Ответы (2)


Было бы неплохо, если бы dependencies поддерживал указатель JSON, но это не так. Вы должны решить это, используя импликацию. Я разбил его, используя definitions, чтобы было понятнее, что происходит.

Сначала я определяю схемы для случаев, которые мы проверяем: присутствует /foo1/bar1 и присутствует /foo2/bar2. С этими двумя определениями я использую anyOf, чтобы сказать, что либо /foo1/bar1 отсутствует, либо требуется /foo2/bar2. Другими словами, /foo1/bar1 подразумевает /foo2/bar2.

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "foo1": {
      "type": [ "object" ],
      "properties": {
        "bar1": { "type": "string" }
      }
    },
    "foo2": {
      "type": [ "object" ],
      "properties": {
        "bar2": { "type": "string" }
      }
    }
  },
  "allOf": [{ "$ref": "#/definitions/foo1-bar1-implies-foo2-bar2" }],
  "dependencies": {
    "foo1": ["foo2"]
  },
  "definitions": {
    "foo1-bar1-implies-foo2-bar2": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/foo1-bar1" } },
        { "$ref": "#/definitions/foo2-bar2" }
      ]
    },
    "foo1-bar1": {
      "properties": {
        "foo1": { "required": ["bar1"] }
      },
      "required": ["foo1"]
    },
    "foo2-bar2": {
      "properties": {
        "foo2": { "required": ["bar2"] }
      },
      "required": ["foo2"]
    }
  }
}
person Jason Desrosiers    schedule 16.03.2018

Довольно сложно добиться этого в черновике 4! Вы можете использовать required в черновике 4, чтобы сделать свойство обязательным в объекте...

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "foo1": {
      "type": [ "object" ],
      "properties": {
        "bar1": { "type": "string" }
      }
    },
    "foo2": {
      "type": [ "object" ],
      "properties": {
        "bar2": { "type": "string" }
      },
      "required": [ "bar2" ]
    }
  }
}

Я не могу повторно запустить это изменение в repl.it, но я проверил его по схеме, которую вы хотите отклонить, используя https://www.jsonschemavalidator.net

Для черновика-7 (который является последним на момент написания) вы можете использовать if, then, else, что может быть более интуитивно понятным, но я думаю, что вам все равно нужно использовать required для достижения этого, поскольку вы хотите, чтобы подсхема в if пройти или не пройти. Ключевые слова для условного применения подсхем.

person Relequestual    schedule 15.03.2018
comment
Я пробовал { "foo1": {}, "foo2": {} }. Он подходит для схемы в вопросе, но не подходит для схемы в вашем ответе. (Ваш ответ на черновик 4 практически нет?) - person neverendingqs; 15.03.2018
comment
Я не ожидал, что вы захотите передать JSON. Я не думаю, что полностью понимаю ваши требования. Не могли бы вы написать некоторую логику sudo, чтобы добавить к вашему вопросу? dependencies не используется в схеме JSON, поэтому ваше использование его в схеме примера не имеет для меня никакого значения. - person Relequestual; 15.03.2018
comment
Я добавил правку вокруг dependencies и спецификации, в которой она появляется. У меня пока нет хорошего примера, который я мог бы опубликовать здесь, который отличается/достаточно анонимно от того, что я изучаю. - person neverendingqs; 15.03.2018
comment
Извините, кажется, что за все время, что я читал схему JSON, я пропустил dependencies. Похоже, другие ответы могут быть больше тем, что вы ищете. - person Relequestual; 16.03.2018