@e22m4u/js-data-schema
v0.0.7
Published
JavaScript модуль для работы со схемой данных
Downloads
751
Readme
@e22m4u/js-data-schema
JavaScript модуль для работы со схемой данных.
Содержание
Установка
npm install @e22m4u/js-data-schemaМодуль поддерживает ESM и CommonJS стандарты.
ESM
import {DataValidator} from '@e22m4u/js-data-schema';CommonJS
const {DataValidator} = require('@e22m4u/js-data-schema');Схема данных
Схема данных позволяет указать допустимый тип значения, схему элементов массива и схему свойств объекта. Схему можно использовать для проверки входящих данных или для преобразования данных к формату схемы.
Свойства схемы:
typeтип данных (см. таблицу ниже);itemsсхема элементов массива, фабрика или имя схемы;propertiesсхема свойств объекта, фабрика или имя схемы;requiredзапрещаетundefinedиnull;defaultзначение по умолчанию или фабрика;
type
Параметр type определяет тип данных. При определении типа можно использовать
константу или название типа в виде строки. Константы проверяются редакторами
кода, что позволяет избежать опечаток при вводе типа.
| константа | значение |
|--------------------|-------------|
| DataType.ANY | "any" |
| DataType.STRING | "string" |
| DataType.NUMBER | "number" |
| DataType.BOOLEAN | "boolean" |
| DataType.ARRAY | "array" |
| DataType.OBJECT | "object" |
items
Параметр items позволяет указать схему для элементов массива. Параметр можно
использовать, только если явно указан тип array. В примере ниже схема массива
включает описание его элементов, которые должны соответствовать числовому типу.
{
type: DataType.ARRAY, // тип данных
items: {
type: DataType.NUMBER // тип элементов
}
}
// [0, 1, 2, undefined, null]Так как все типы допускают undefined и null в качестве пустых значений,
рекомендуется использовать параметр required в определении схемы элемента,
чтобы запретить данные значения в составе массива.
{
type: DataType.ARRAY,
items: {
type: DataType.NUMBER,
required: true // запрещает undefined, null
}
}
// [0, 1, 2]properties
Параметр properties позволяет указать схему каждого свойства объекта.
Параметр можно использовать, только если явно указан тип object. В примере
ниже используется схема объекта с двумя свойствами.
{
type: DataType.OBJECT, // тип данных
properties: {
name: {
type: DataType.STRING // тип свойства "name"
},
age: {
type: DataType.NUMBER // тип свойства "age"
}
}
}
// {
// "name": "John",
// "age": 27
// }Свойства объекта могут быть обязательными. Для этого используется параметр
required в схеме соответствующего свойства. Если параметр указан, то при
проверке значений undefined и null будет выброшена ошибка.
{
type: DataType.OBJECT,
properties: {
name: {
type: DataType.STRING,
required: true // запрещает undefined и null
},
age: {
type: DataType.NUMBER,
required: true // запрещает undefined и null
}
}
}required
По умолчанию все типы допускают undefined и null в качестве пустых
значений. Параметр required может быть использован для явного запрета
таких значений при проверке данных.
{
type: DataType.STRING, // тип данных
required: true // запрещает undefined и null
}
// "foo", "bar" ...default
Значение по умолчанию можно указать в параметре default. Указанное значение
будет использовано вместо undefined и null. Если значение параметра
является объектом или массивом, то итоговые данные получат его копию.
{
type: DataType.STRING, // тип данных
default: 'N/A' // значение по умолчанию
}Проверка данных
Модуль экспортирует сервис DataValidator, с помощью которого выполняется
проверка соответствия данных указанной схеме. Пример ниже демонстрирует
создание экземпляра сервиса и проверку примитивных значений.
import {DataValidator, DataType} from '@e22m4u/js-data-schema';
const validator = new DataValidator();
const numberSchema = {type: DataType.NUMBER};
// OK
validator.validate(10, numberSchema);
validator.validate(0, numberSchema);
validator.validate(undefined, numberSchema);
validator.validate(null, numberSchema);
// выбросит DataValidationError
validator.validate('str', numberSchema);
validator.validate(true, numberSchema);
validator.validate([1, 2, 3], numberSchema);
validator.validate({foo: 'bar'}, numberSchema);Как видно из примера выше, undefined и null являются допустимыми значениями,
несмотря на указанный тип данных. Чтобы изменить это поведение, используется
параметр required, запрещая пустые значения для данной схемы.
import {DataValidator, DataType} from '@e22m4u/js-data-schema';
const validator = new DataValidator();
const requiredNumberSchema = {
type: DataType.NUMBER,
required: true // запрещает undefined и null
};
// OK
validator.validate(10, requiredNumberSchema);
validator.validate(0, requiredNumberSchema);
validator.validate(-10, requiredNumberSchema);
// выбросит DataValidationError
validator.validate(undefined, requiredNumberSchema);
validator.validate(null, requiredNumberSchema);Парсинг данных
Сервис DataParser спроектирован для приведения данных в соответствие
указанной схеме. Приведение выполняется с учетом возможных ошибок ввода.
К примеру, если схема ожидает число, но входящие данные содержат буквы,
то будет выброшена ошибка.
import {DataParser, DataType} from '@e22m4u/js-data-schema';
const parser = new DataParser();
parser.parse('10', {type: DataType.NUMBER}); // 10
parser.parse('10.5', {type: DataType.NUMBER}); // 10.5
parser.parse('10abc', {type: DataType.NUMBER}); // DataParsingErrorМассивы и объекты могут быть представлены в виде JSON. Метод parse
поддерживает данный формат и выполняет проверку разобранного значения.
К примеру, если элементы массива не соответствуют определению схемы,
то будет выброшена ошибка.
import {DataParser, DataType} from '@e22m4u/js-data-schema';
const parser = new DataParser();
const numberListSchema = {
type: DataType.ARRAY,
items: {
type: DataType.NUMBER,
required: true, // запрещает undefined и null
},
};
parser.parse('[1, 2, 3]', numberListSchema); // [1, 2, 3]
parser.parse('[1, 2, null]', numberListSchema); // DataParsingErrorПри разборе данных учитывается параметр default. Если исходным значением
является undefined или null, то будет использовано значение по умолчанию.
Значение данного параметра должно соответствовать указанному типу.
import {DataParser, DataType} from '@e22m4u/js-data-schema';
const parser = new DataParser();
const schema = {
type: DataType.NUMBER,
default: 5,
};
parser.parse('10', schema); // 10
parser.parse(undefined, schema); // 5
parser.parse('N/A', schema); // DataParsingErrorПодмену исходных значений на значения по умолчанию можно отключить, если
передать параметр noDefaultValues в настройки метода parse, как это
показано ниже.
import {DataParser, DataType} from '@e22m4u/js-data-schema';
const parser = new DataParser();
const schema = {
type: DataType.NUMBER,
default: 5,
};
// используется значение по умолчанию
parser.parse(undefined, schema); // 5
// с параметром "noDefaultValues" значение по умолчанию игнорируется
parser.parse(undefined, schema, {noDefaultValues: true}); // undefinedЕсли схема объекта содержит параметр properties, то свойства исходного
объекта, не описанные в схеме, исключаются из результата. Итоговый объект
будет содержать только те свойства, которые были определены явно.
const schema = {
type: DataType.OBJECT,
properties: {
name: {
type: DataType.STRING
},
},
};
const data = {
name: 'Fedor',
isAdmin: true, // лишнее свойство
metadata: 'ignored' // лишнее свойство
};
const result = parser.parse(data, schema);
console.log(result);
// {"name": "Fedor"}Чтобы избежать удаления свойств, не указанных в схеме данных, используется
параметр keepUnknownProperties, который позволяет сохранить все свойства
исходного объекта.
const schema = {
type: DataType.OBJECT,
properties: {
id: {type: DataType.NUMBER},
},
};
const data = {
id: 1,
role: 'admin',
};
// по умолчанию лишние свойства удаляются
parser.parse(data, schema);
// {id: 1}
// с параметром "keepUnknownProperties" свойства сохраняются
parser.parse(data, schema, {keepUnknownProperties: true});
// {id: 1, role: 'admin'}Именованные схемы
Сервисы для проверки и парсинга данных позволяют регистрировать схемы данных
по уникальному имени методом defineSchema. В дальнейшем именованные схемы
могут быть использованы вместо объекта схемы аналогичным образом.
import {DataValidator, DataParser, DataType} from '@e22m4u/js-data-schema';
const validator = new DataValidator();
const parser = new DataParser();
const schema = {
type: DataType.ARRAY,
items: {
type: DataType.STRING,
required: true,
},
};
validator.defineSchema({name: 'mySchema', schema});
parser.defineSchema({name: 'mySchema', schema});Регистрация схем может выполняться централизованно через встроенный реестр. Этого можно добиться, используя сервис-контейнер, который выступает в роли точки входа в приложение.
import {ServiceContainer} from '@e22m4u/js-service';
import {
DataType,
DataParser,
DataValidator,
DataSchemaRegistry,
} from '@e22m4u/js-data-schema';
const app = new ServiceContainer(); // сервис-контейнер
const registry = app.get(DataSchemaRegistry); // реестр схем данных
registry.defineSchema({
name: 'mySchema',
schema: {
type: DataType.ARRAY,
items: {
type: DataType.STRING,
required: true,
},
},
});
// порядок доступа к сервисам и порядок
// регистрации схем значения не имеет
const validator = app.get(DataValidator);
const parser = app.get(DataParser);В примере выше оба сервиса используют общий реестр и знают о зарегистрированной
схеме mySchema, что избавляет от необходимости синхронизации между сервисами
данного модуля.
Использование именованных схем
Зарегистрированное имя можно использовать вместо объекта схемы. Пример ниже
демонстрирует регистрацию схемы mySchema и проверку массива с помощью
данного имени.
validator.defineSchema({
name: 'mySchema',
schema: {
type: DataType.STRING,
required: true,
},
});
validator.validate(['a', 'b', 'c'], 'mySchema'); // OK
validator.validate(['a', 'b', 10], 'mySchema'); // DataValidationErrorЗарегистрированные имена можно встраивать в другие схемы. Ниже приводится пример разбора JSON строки с использованием именованной схемы внутри схемы массива.
parser.defineSchema({
name: 'user', // имя схемы
schema: {
type: DataType.OBJECT,
properties: {
name: {
type: DataType.STRING,
required: true,
},
age: {
type: DataType.NUMBER,
default: 0,
},
},
},
});
const jsonData = `[{"name": "John","age": 35},{"name": "Tommy"}]`;
const users = parser.parse(jsonData, {
type: DataType.ARRAY,
items: 'user', // <= именованная схема
});
console.log(users);
// [
// {
// name: 'John',
// age: 35
// },
// {
// name: 'Tommy',
// age: 0
// }
// ]Если именованная схема описывает объект, то допускается передача имени схемы
в параметр properties, что позволяет переопределить остальные параметры
зарегистрированной схемы.
validator.validate(data, {
type: DataType.OBJECT,
properties: 'user', // имя схема вместо схемы свойств
required: true, // переопределение параметра схемы "user"
});Тесты
npm run testЛицензия
MIT
