需要更好的 JSON 模式来验证稀疏矩阵数据对象
Need better JSON Schema to validate sparse matrix data object
我需要验证 JavaScript 中的复杂对象。
对象基于字典:
var dict = {'1':true,'2':true,'3':true};
成对的对象存储矩阵(通常不完整):
var obj = {'1':{
'1': 'str1',
'2': 'str2',
'3': 'str3',
},'2':{
'1': 'str1',
'2': 'str2',
}
};
我使用 AJV 验证器制作验证模式。
架构要求:
- 第一级对象仅包含字典中的属性。
- 二级对象仅包含字典中的属性。
- 数据是一个字符串
正在生成架构:
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 秒(验证快,编译慢)。此外,它会不时抛出内存异常。是否可以做出更好的验证模式?
考虑到您正在验证 40000 个属性,内存异常在这里并不奇怪。您的验证函数代码大小应在 30Mb 左右。
您可以使用我添加到 v5/6 proposals and that is available in ajv-keywords 包中的 属性Names 关键字。
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
}
}
}
}
};
属性名称看起来更简单,我认为应该更快。
通过映射 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>
我需要验证 JavaScript 中的复杂对象。
对象基于字典:
var dict = {'1':true,'2':true,'3':true};
成对的对象存储矩阵(通常不完整):
var obj = {'1':{
'1': 'str1',
'2': 'str2',
'3': 'str3',
},'2':{
'1': 'str1',
'2': 'str2',
}
};
我使用 AJV 验证器制作验证模式。
架构要求:
- 第一级对象仅包含字典中的属性。
- 二级对象仅包含字典中的属性。
- 数据是一个字符串
正在生成架构:
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 秒(验证快,编译慢)。此外,它会不时抛出内存异常。是否可以做出更好的验证模式?
考虑到您正在验证 40000 个属性,内存异常在这里并不奇怪。您的验证函数代码大小应在 30Mb 左右。
您可以使用我添加到 v5/6 proposals and that is available in ajv-keywords 包中的 属性Names 关键字。
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
}
}
}
}
};
属性名称看起来更简单,我认为应该更快。
通过映射 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>