Могу ли я проверить дату с помощью схемы ajv json без преобразования даты в строку?

У меня есть объект, который содержит одно или несколько свойств типа date. Я хотел бы проверить объект с помощью пакета валидатора схемы ajv json. Я мог преобразовать свойства типа date в строку с помощью 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 - это дата, а не строка.


person A. Bolleter    schedule 04.04.2019    source источник
comment
Взгляните на этот плагин, который github.com/epoberezkin/ajv-keywords связан с тем, кто вы ищу я думаю   -  person leocoder    schedule 10.09.2019
comment
Просто измените схему ajv с type: string на type: object, и встроенный формат даты и времени ajv будет работать. Проверено в ajv версии 6.10.2.   -  person Ananda Masri    schedule 21.11.2019
comment
Поскольку объект Date больше (и менее переносим), чем строка даты / времени, я бы рекомендовал преобразовать ваши объекты Date в строки, особенно если вы планируете отправить проверенные данные на свой внутренний сервер для повторной отправки. Проверка. Не все внутренние серверные платформы могут легко проверить объект Date javascript.   -  person Ananda Masri    schedule 21.11.2019
comment
@leocoder, как именно предложенный вами пакет решит проблему? Пакет ajv уже позволяет определять собственные валидаторы ajv.   -  person Ananda Masri    schedule 21.11.2019


Ответы (2)


Просто измените схему 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));
person Ananda Masri    schedule 20.11.2019
comment
Тест пройден с {date: 1}, поэтому ответ недействителен. - person Polv; 17.05.2020
comment
@Polv, OP спросил: Могу ли я проверить дату с помощью схемы ajv json без преобразования даты в строку ?. Я обновил свой ответ, чтобы удовлетворить ваши конкретные требования к проверке, включив в схему проверки обязательные и дополнительные свойства. - person Ananda Masri; 03.08.2020

Один из подходящих способов - сначала преобразовать в объект, совместимый со схемой 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
}
person Polv    schedule 17.05.2020
comment
Как это должно работать? Насколько я могу судить, makeJsonSchemaCompatible(new Date()) возвращает только { __className: "Date" }, т.е. все фактические данные Date теряются. Кроме того, JSON.parse(JSON.stringify(new Date())) не выполняет двусторонний обмен должным образом. Тип изменится с Date на строковый. - person bluenote10; 22.05.2021
comment
Идея в том, что есть оживитель и заменитель; но мне нужно будет исправить мой код. - person Polv; 22.05.2021