/ / Нуждаете се от по-добра схема JSON за валидиране на обект от данни с ограничена матрица - javascript, валидиране, jsonschema, ajv

Нуждаете се от по-добра схема JSON за валидиране на обект от данни с ограничена матрица - javascript, валидиране, jsonschema, ajv

Трябва да валидирам сложен обект в JavaScript.

Обектът се основава на речника:

var dict = {"1":true,"2":true,"3":true};

Матрица за съхраняване на обекти на двойки (обикновено не е пълна):

var obj = {"1":{
"1": "str1",
"2": "str2",
"3": "str3",
},"2":{
"1": "str1",
"2": "str2",
}
};

Правя схема за валидиране с AJV валидатор.

Изисквания към схемата:

  1. Обектът от 1-во ниво съдържа само свойства от речника.
  2. Обектът на второ ниво съдържа само свойства от речника.
  3. данните са низ

Генериране на схема:

var dict = {"1":true,"2":true,"3":true};

var subProperties = R.map(function(item){
return {
"type" : "string",
"minLength": 1,
}
}, dict);
var root = {
"type" : "object",
"additionalProperties" : false
};
root.properties = R.map(function(item){
return {
"type" : "object",
"properties" : subProperties,
"additionalProperties" : false
};
}, dict);

console.log(root)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.9.0/ajv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>

Тази схема работи добре, но проблемът епроизводителност. Когато речникът съдържа 200 елемента, за съставянето на тази схема са необходими 10 секунди (валидирането е бързо, компилацията е бавна). Освен това от време на време изхвърля изключение от паметта. Възможно ли е да се направи по-добра схема за валидиране?

Отговори:

2 за отговор № 1

Изключенията от паметта тук не са изненадващи, като се има предвид, че потвърждавате 40000 свойства. Размерът на кода на валидиращата ви функция трябва да е около 30Mb.

Можете да използвате ключовата дума propertyNames, която добавих към v5 / 6 предложения и това е достъпно в ajv-ключови думи пакет.

var dict = ["1", "2", "3"];
var schema = {
type: "object",
propertyNames: { enum: dict },
additionalProperties: {
type: "object",
propertyNames: { enum: dict },
additionalProperties: {
type: "string",
minLength: 1
}
}
};

var ajv = require("ajv")();
require("ajv-keywords")(ajv, "propertyNames");

var validate = ajv.compile(schema);

Тази схема е мъничка, но прави същото.

Можете да постигнете същото с помощта на ключовата дума patternProperties, която съществува в текущата стандартна версия (със синтаксис на свойството es6):

var names = "^(1|2|3)$";
var schema = {
type: "object",
additionalProperties: false,
patternProperties: {
[names]: {
type: "object",
additionalProperties: false,
patternProperties: {
[names]: {
type: "string",
minLength: 1
}
}
}
}
};

propertyNames изглежда по-опростен и трябва да бъде по-бърз според мен.


1 за отговор № 2

Чрез картографиране над items резултатът не е 1 но N схема (т.е. ако имате 200 елемента, създайте 200 схеми с единствената цел да валидирате ключа).

Алтернативата е или да се използва patternProperties с огромен 200 ключ дълъг RegExp или по-просто, просто валидирайте обекта ръчно.

var dict = {"1":true,"2":true,"3":true};

var monsterRegex = "^" + Object.keys(dict).join("|") + "$"

var valSchema = {
type: "string",
minLength: 1
}
var keySchema = {
type: "object",
additionalProperties: false,
patternProperties: {}
}
keySchema.patternProperties[monsterRegex] = valSchema

var objSchema = {
type: "object",
additionalProperties: false,
patternProperties: {}
}
objSchema.patternProperties[monsterRegex] = keySchema

console.log(objSchema)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.9.0/ajv.min.js"></script>