是否可以使用 ajv json 架构验证日期,而无需将日期转换为字符串



我有一个对象,其中包含一个或多个类型为date的属性。我想使用 ajv json 架构验证器包来验证对象。我可以使用 toISOString(( 将日期类型的属性转换为字符串。但是对象可以安静地大,因此我不想转换整个对象的所有日期属性。除了将日期转换为字符串之外,还有其他解决方案吗?我可以以某种方式创建自定义 ajv 架构验证器吗?

 // My example schema
const schema = {
  "properties": {
    "createdAt": { 
       "type": "string",
       "format": "date-time"
    },
       "lastName": { "type": "string" },
       "firstName": { "type": "string" }
  }
};
// My example testobject
const testObj = {
   createdAt: new Date(),
   lastName: "Doe",
   firstName: "John"
}
// The validation
const validate = ajv.compile(schema);
const valid = validate(testObj);
if(!valid) console.log('Invalid: ' + ajv.errorsText(validate.errors));

这将执行控制台日志,因为testObj.createdAt是一个日期而不是一个字符串。

只需将 ajv 架构从 "type": "string" 更改为 "type": "object",内置的 ajv 日期时间格式即可。 这是一个工作的小提琴。

您还可以定义自定义 ajv 格式来验证 Date 对象(或字符串(,如下所示:

ajv = new Ajv();
ajv.addFormat('custom-date-time', function(dateTimeString) {
  if (typeof dateTimeString === 'object') {
    dateTimeString = dateTimeString.toISOString();
  }
  return !isNaN(Date.parse(dateTimeString));  // any test that returns true/false 
});

。并在 AJV 架构中调用自定义格式,如下所示:

const schema = {
  "properties": {
    "createdAt": {
      "type": "object",
      "format": "custom-date-time"
将它们

放在一起,这是创建自定义日期格式的代码和工作小提琴:

// My example schema
const schema = {
  "properties": {
    "createdAt": {
      "type": "object",
      "format": "custom-date-time"
    },
    "lastName": {
      "type": "string"
    },
    "firstName": {
      "type": "string"
    },
    "required": [ 'createdAt', 'lastName', 'firstName' ],
    "additionalProperties": false,
  }
};
// My example testobject
const testObj = {
  createdAt: new Date(),
  lastName: "Doe",
  firstName: "John"
}

// The validation
ajv = new Ajv();
ajv.addFormat('custom-date-time', function(dateTimeString) {
  if (typeof dateTimeString === 'object') {
    dateTimeString = dateTimeString.toISOString();
  }
  return !isNaN(Date.parse(dateTimeString));  // return true/false 
});
const validate = ajv.compile(schema);
const valid = validate(testObj);
if (valid)
  alert('valid');
else
  alert('Invalid: ' + ajv.errorsText(validate.errors));

其中一个有效的方法是首先转换为与 JSON 架构兼容的对象。

function makeJsonSchemaCompatible (obj) {
  if (Array.isArray(obj)) {
    return obj.map((subObj) => makeJsonSchemaCompatible(subObj))
  } else if (obj && typeof obj === 'object') {
    const replacement = {}
    const className = obj.constructor.name
    if (className !== 'Object') {
      replacement.__className = className
    }
    Object.entries(obj).map(([k, v]) => { replacement[k] = makeJsonSchemaCompatible(v) })
    return replacement
  }
  return obj
}

不幸的是,format 属性不适用于object类型,因此自定义格式不是一个选项。但是,我能够添加一个自定义关键字(灵感来自查看instance关键字,它实际上可以让您完成一半(,这给了我所需的结果(即值必须是 Date 对象并且 Date 必须有效(。

const { equal } = require('assert');
const Ajv = require('ajv');
const { _ } = require('ajv');
const ajv = new Ajv();
const schema = {
  type: 'object',
  properties: {
    jsdate: {
      type: 'object',
      isDate: true,
    },
  },
};
ajv.addKeyword({
  keyword: 'isDate',
  type: 'object',
  code(ctx) {
    const { data } = ctx;
    ctx.pass(_`${data} instanceof Date && !isNaN(+${data})`);
  },
});
const validate = ajv.compile(schema);
equal(validate({ jsdate: new Date() }), true, 'should succeed');
equal(validate({ jsdate: {} }), false, 'should fail for random object');
equal(
  validate({ jsdate: '2001-01-01' }),
  false,
  'should fail for valid date string'
);
equal(
  validate({ jsdate: new Date('rubbish') }),
  false,
  'should fail if Date is invalid'
);

似乎您可以使用 instanceof 关键字(ajv 关键字的一部分(来达到预期的结果:.

const Ajv = require("ajv");
const addKeywords = require("ajv-keywords");
const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
addKeywords(ajv);
// My example schema
const schema = {
  type: "object",
  properties: {
    createdAt: {
      instanceof: "Date",
    },
    lastName: { type: "string" },
    firstName: { type: "string" },
  },
};
// My example testobject
const testObj = {
  createdAt: new Date(),
  lastName: "Doe",
  firstName: "John",
};
// The validation
const validate = ajv.compile(schema);
const valid = validate(testObj);
if (!valid) console.log("Invalid: " + ajv.errorsText(validate.errors));

相关内容

  • 没有找到相关文章

最新更新