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

时间:2018-03-16 07:44:35

标签: json jsonschema json-schema-validator ajv

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

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)

一切都很好。现在我需要使用$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"
      }
    }
  }
};

但看起来好像$data ref不支持自定义字段。正如文档中所提到的,$ data ref。

仅支持以下字段
  关键字支持

$ data reference:const,enum,format,   最大/最小,exclusiveMaximum / exclusiveMinimum,maxLength /   minLength,maxItems / minItems,maxProperties / minProperties,   formatMaximum / formatMinimum,formatExclusiveMaximum /   formatExclusiveMinimum,multipleOf,pattern,required,uniqueItems。

获取值的一种方法是,我使用validate函数data, dataPath, parentData, parentDataProperty的参数并编写逻辑来提取$data ref定义的字段值。但我不确定这是否是实现目标的正确方法。有人可以帮我这个吗?这是plunkr to play。感谢。

1 个答案:

答案 0 :(得分:0)

在挖掘documentation一段时间后,我终于开始工作了。分享后方读者的解决方案总是好的。这就是我所做的:

// 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)

显着的选项是$data。需要设置true。这是工作plunkr