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

Keys in One Object Must be the Same as Keys in Another Object

初始设置

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

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,打印 "Valid!" 但必须是 "Invalid"

'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. 在根级别创建另一个 属性,例如必需的属性。它的值应该是一个数组,其中包含您希望在顶层和插件内部都拥有的属性列表。然后你可以在顶层和插件内部使用 required with $data 指向这个数组。 请参阅此处的示例:https://runkit.com/esp/581ce9faca86cc0013c4f43f

  2. 使用custom keyword(s).

  3. 检查代码中的这一要求 - JSON 架构中没有办法说一个对象中的键应该与另一个对象中的键相同(除了上述选项)。