Ajv:如何利用自定义关键字来利用 $data 引用?

Hit*_*mar 1 json jsonschema json-schema-validator ajv

我在我的项目中使用Ajv。我正在尝试在 api 的帮助下添加自定义关键字ajv.addKeyword。我可以通过这样做添加关键字(借自文档):

var ajv = new Ajv({
  $data: true
});

ajv.addKeyword('range', {
  type: 'number',
  compile: function(sch, parentSchema) {
    var min = sch[0];
    var max = sch[1];
    return parentSchema.exclusiveRange === true ? function(data) {
      return data > min && data < max;
    } : function(data, dataPath, parentData, parentDataProperty) {
      return data >= min && data <= max;
    }
  }
});

var schema = {
  "properties": {
    "smaller": {
      "type": "number"
    },
    "larger": {
      "type": "number",
      "range": [2, 10]
    }
  }
};

var validData = {
  smaller: 15,
  larger: 17
};

let validateData = ajv.compile(schema);
validateData(validData);
console.log('Errors after validations --> ', validateData.errors)
Run Code Online (Sandbox Code Playgroud)

一切正常。现在我需要使用$data自定义字段的原因数据将是其他字段的值。为了实现它,这就是我对我的模式所做的尝试:

var schema = {
  "properties": {
    "smaller": {
      "type": "number"
    },
    "larger": {
      "type": "number",
      // "range": [2, 10],
      "range": {
        "$data": "1/myRange" // referencing to myRange
      }
    },
    "myRange": {
      type: "array",
      items: {
        type: "number"
      }
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

但 ref 似乎还不支持自定义字段$data。正如文档中提到的,$data ref 仅支持以下字段。

关键字中支持 $data 引用:const、enum、format、maximum/minimum、exclusiveMaximum / ExclusiveMinimum、maxLength / minLength、maxItems / minItems、maxProperties / minProperties、formatMaximum / formatMinimum、formatExclusiveMaximum / formatExclusiveMinimum、multipleOf、pattern、required、uniqueItems 。

获取该值的一种方法是,我使用验证函数的参数data, dataPath, parentData, parentDataProperty并编写逻辑来提取由 ref 定义的字段的值$data。但我不确定这是否是实现这一目标的正确方法。有人可以帮我解决这个问题吗?这是要玩的 plunkr。谢谢。

Hit*_*mar 8

经过一段时间的文档挖掘后,我终于让它工作了。为后面的读者分享解决方案总是好的。这就是我所做的:

// Code goes here
console.clear();
var ajv = new Ajv({
  $data: true
});


ajv.addKeyword('range', {
  type: 'number',
  errors: true,
  $data: true, // important part
  validate: function(schema, data, parentSchema) {
    const {
      exclusiveRange: isExclusive
    } = parentSchema;
    const [min, max] = schema;
    if (isExclusive) {
      return data > min && data < max;
    }
    return data >= min && data <= max;
  }
});

var schema = {
  "properties": {
    "smaller": {
      "type": "number",
      "maximum": {
        "$data": "1/larger"
      }
    },
    "larger": {
      "type": "number",
      // "range": [2, 10],
      "range": {
        "$data": "1/myRange"
      },
      "exclusiveRange": true
    },
    "myRange": {
      type: "array",
      items: {
        type: "number"
      }
    }
  }
};


var validData = {
  smaller: 3,
  larger: 7,
  myRange: [2, 10]
};

let validateData = ajv.compile(schema);
validateData(validData);
console.log(ajv);
console.log('Errors after validations --> ', validateData.errors)
Run Code Online (Sandbox Code Playgroud)

显着的选项已$data在定义中。需要对其进行设置true。这是工作中的plunkr