/ / Besoin d'un meilleur schéma JSON pour valider un objet de données de matrice éparse - javascript, validation, jsonschema, ajv

Besoin d'un meilleur schéma JSON pour valider un objet de données à matrice clairsemée - javascript, validation, jsonschema, ajv

J'ai besoin de valider un objet complexe en JavaScript.

L'objet est basé sur le dictionnaire:

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

Matrice de magasin d'objets de paires (généralement pas pleine):

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

Je fais un schéma de validation avec le validateur AJV.

Exigences du schéma:

  1. L'objet de 1er niveau contient uniquement les propriétés du dictionnaire.
  2. L'objet de deuxième niveau contient uniquement les propriétés du dictionnaire.
  3. les données sont une chaîne

Génération du schéma:

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>

Ce schéma fonctionne bien mais le problème estperformance. Lorsque le dictionnaire contient 200 éléments, il faut 10 secondes pour compiler ce schéma (la validation est rapide, la compilation est lente). De plus, il jette de temps en temps des exceptions de mémoire. Est-il possible de faire un meilleur schéma de validation?

Réponses:

2 pour la réponse № 1

Les exceptions de mémoire ne sont pas surprenantes ici étant donné que vous validez 40000 propriétés. La taille de votre code de fonction de validation doit être d'environ 30 Mo.

Vous pouvez utiliser le mot-clé propertyNames auquel j'ai ajouté propositions v5 / 6 et qui est disponible dans mots-clés ajv paquet.

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);

Ce schéma est minuscule mais fait la même chose.

Vous pouvez obtenir la même chose en utilisant le mot-clé patternProperties qui existe dans la version standard actuelle (avec la syntaxe de propriété 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 semble plus simple et devrait être plus rapide je pense.


1 pour la réponse № 2

En cartographiant sur items le résultat n'est pas 1 mais N schéma (c'est-à-dire que si vous avez 200 éléments, 200 schémas sont créés dans le seul but de valider la clé).

L'alternative consiste soit à utiliser patternProperties avec une énorme clé de 200 longs RegExp ou plus simplement, validez simplement l'objet manuellement.

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>