一个对象中的键必须与另一个对象中的键相同

时间:2016-11-04 17:44:07

标签: jsonschema ajv

初始设置

你有一个用于保持配置的JavaScript对象,它可以通过插件扩展,每个插件在configs对象上都有一个版本和一个属性。

const CONFIGS = {
  plugins: {
    plugins: { version: '0.15' }, // Plugins is a plugin itself.
    proxies: { version: '0.15' }  // Used to configure proxies.
  },
  proxies: {
    HTTPS: ['satan.hell:666']
  }
}

问题

如何在JSON模式中表达,CONFIGS.plugins的每个键必须在CONFIGS对象的根上具有相应的属性,反之亦然。

我的失败尝试

ajv是4.8.2,打印“有效!”但必须“无效”

'use strict';

var Ajv = require('ajv');
var ajv = Ajv({allErrors: true, v5: true});

var schema = {

  definitions: {
    pluginDescription: {
      type: "object",
      properties: {
        version: { type: "string" }
      },
      required: ["version"],
      additionalProperties: false
    }
  },

  type: "object",
  properties: {

    plugins: {
      type: "object",
      properties: {

        plugins: {
          $ref: "#/definitions/pluginDescription"
        }

      },
      required: ["plugins"],
      additionalProperties: {
        $ref: "#/definitions/pluginDescription"
      }
    }

  },
  required: { $data: "0/plugins/#" }, // current obj > plugins > all props?
  additionalProperties: false
};

var validate = ajv.compile(schema);

test({
  plugins: {
    plugins: { version: 'def' },
    proxies: { version: 'abc' }
  }
  // Sic! No `proxies` prop, but must be.
});

function test(data) {
  var valid = validate(data);
  if (valid) console.log('Valid!');
  else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}

1 个答案:

答案 0 :(得分:1)

这里有三种解决方案:

  1. 在根级别创建另一个属性,例如requiredProperties。它的值应该是一个数组,其中包含您希望在顶层和内部插件中具有的属性列表。然后你可以在顶层和内部插件中使用指向这个数组的$ data。 请参阅此处的示例:https://runkit.com/esp/581ce9faca86cc0013c4f43f

  2. 使用custom keyword(s)

  3. 在代码中检查此要求 - 在JSON模式中无法说一个对象中的键应与另一个对象中的键相同(除了上述选项)。