JavaScript модуль для работы со схемой данных
|
|
6 дней назад | |
|---|---|---|
| .husky | 3 недель назад | |
| dist | 6 дней назад | |
| src | 6 дней назад | |
| .c8rc | 3 недель назад | |
| .commitlintrc | 3 недель назад | |
| .editorconfig | 3 недель назад | |
| .gitignore | 3 недель назад | |
| .mocharc.json | 3 недель назад | |
| .prettierrc | 3 недель назад | |
| LICENSE | 3 недель назад | |
| README.md | 1 неделя назад | |
| build-cjs.js | 3 недель назад | |
| eslint.config.js | 3 недель назад | |
| package.json | 6 дней назад | |
| tsconfig.json | 3 недель назад |
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 определяет тип данных. При определении
типа можно использовать константу или название типа в виде строки.
Константы проверяются редакторами кода, что позволяет избежать опечаток
при вводе типа.
| константа | значение |
|---|---|
DataType.ANY |
"any" |
DataType.STRING |
"string" |
DataType.NUMBER |
"number" |
DataType.BOOLEAN |
"boolean" |
DataType.ARRAY |
"array" |
DataType.OBJECT |
"object" |
Параметр 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 позволяет указать схему каждого
свойства объекта. Параметр можно использовать, только если явно указан
тип 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
}
}
}
По умолчанию все типы допускают undefined и
null в качестве пустых значений. Параметр
required может быть использован для явного запрета таких
значений при проверке данных.
{
type: DataType.STRING, // тип данных
required: true // запрещает undefined и null
}
// "foo", "bar" ...
Значение по умолчанию можно указать в параметре 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