dependencies rule
parent
4a7a586bac
commit
c4816e4836
|
@ -21,6 +21,7 @@ function compile(schema) {
|
|||
_validate: _validateTemplate,
|
||||
copy: copy,
|
||||
getDataType: getDataType,
|
||||
escapeQuotes: escapeQuotes,
|
||||
stableStringify: stableStringify,
|
||||
opts: this.opts
|
||||
});
|
||||
|
@ -53,3 +54,7 @@ function copy(o, to) {
|
|||
return to;
|
||||
}
|
||||
|
||||
|
||||
function escapeQuotes(str) {
|
||||
return str.replace(/"/g, '\\"');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var errors = [];
|
||||
|
||||
{{
|
||||
var $schemaDeps = {}
|
||||
, $propertyDeps = {};
|
||||
|
||||
for ($property in it.schema) {
|
||||
var $schema = it.schema[$property];
|
||||
var $deps = Array.isArray($schema) ? $propertyDeps : $schemaDeps;
|
||||
$deps[$property] = $schema;
|
||||
}
|
||||
}}
|
||||
|
||||
{{ for ($property in $propertyDeps) { }}
|
||||
if (data.hasOwnProperty('{{= $property }}')) {
|
||||
{{ $deps = $propertyDeps[$property]; }}
|
||||
var valid = {{~ $deps:$dep:$i }}{{?$i}} && {{?}}data.hasOwnProperty('{{= $dep}}'){{~}};
|
||||
if (!valid) {
|
||||
var error = {
|
||||
keyword: 'dependencies',
|
||||
schema: self.schema{{= it.schemaPath }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, {{? $deps.length == 1 }}property {{= $deps[0] }} is{{??}}properties {{= $deps.join(",") }} are{{?}} required when property {{= $property }} is present'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
};
|
||||
|
||||
{{? it.opts.allErrors }}
|
||||
errors.push(error);
|
||||
{{??}}
|
||||
return { valid: false, errors: [error] };
|
||||
{{?}}
|
||||
}
|
||||
}
|
||||
{{ } }}
|
||||
|
||||
{{ for ($property in $schemaDeps) { }}
|
||||
if (data.hasOwnProperty('{{= $property }}')) {
|
||||
{{
|
||||
var $schema = $schemaDeps[$property];
|
||||
var $it = it.copy(it);
|
||||
$it.schema = $schema;
|
||||
$it.schemaPath = it.schemaPath + '["' + it.escapeQuotes($property) + '"]';
|
||||
}}
|
||||
|
||||
var result = ({{= it._validate($it) }})(data, dataType, dataPath);
|
||||
|
||||
if (!result.valid) {
|
||||
{{? it.opts.allErrors }}
|
||||
errors.push.apply(errors, result.errors);
|
||||
{{??}}
|
||||
return { valid: false, errors: result.errors };
|
||||
{{?}}
|
||||
}
|
||||
}
|
||||
{{ } }}
|
||||
|
||||
{{? it.opts.allErrors }}
|
||||
return { valid: !errors.length, errors: errors };
|
||||
{{??}}
|
||||
return { valid: true, errors: [] };
|
||||
{{?}}
|
||||
}
|
|
@ -66,10 +66,10 @@ var RULES = module.exports = {
|
|||
code: fs.readFileSync(__dirname + '/properties.dot.js'),
|
||||
type: 'object'
|
||||
},
|
||||
// dependencies: {
|
||||
// code: '',
|
||||
// type: 'object'
|
||||
// }
|
||||
dependencies: {
|
||||
code: fs.readFileSync(__dirname + '/dependencies.dot.js'),
|
||||
type: 'object'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7,14 +7,15 @@ var fs = require('fs')
|
|||
|
||||
var ONLY_RULES;
|
||||
// ONLY_RULES = ['enum'];
|
||||
ONLY_RULES = [
|
||||
'type', 'not', 'allOf', 'anyOf', 'oneOf', 'enum',
|
||||
'maximum', 'minimum', 'multipleOf',
|
||||
'maxLength', 'minLength', 'pattern',
|
||||
'properties', 'patternProperties', 'additionalProperties',
|
||||
'required', 'maxProperties', 'minProperties',
|
||||
'maxItems', 'minItems', 'items', 'additionalItems', 'uniqueItems'
|
||||
];
|
||||
// ONLY_RULES = [
|
||||
// 'type', 'not', 'allOf', 'anyOf', 'oneOf', 'enum',
|
||||
// 'maximum', 'minimum', 'multipleOf',
|
||||
// 'maxLength', 'minLength', 'pattern',
|
||||
// 'properties', 'patternProperties', 'additionalProperties',
|
||||
// 'dependencies',
|
||||
// 'required', 'maxProperties', 'minProperties',
|
||||
// 'maxItems', 'minItems', 'items', 'additionalItems', 'uniqueItems'
|
||||
// ];
|
||||
|
||||
|
||||
var Jv = require('../lib/jv')
|
||||
|
@ -30,14 +31,14 @@ describe.only('JSON-Schema tests', function () {
|
|||
describe(file.name, function() {
|
||||
var testSets = require(file.path);
|
||||
testSets.forEach(function (testSet) {
|
||||
// if (testSet.description != 'additionalProperties can exist by itself') return;
|
||||
// if (testSet.description != 'multiple dependencies') return;
|
||||
describe(testSet.description, function() {
|
||||
// it(testSet.description, function() {
|
||||
var validate = jv.compile(testSet.schema);
|
||||
var fullValidate = fullJv.compile(testSet.schema);
|
||||
|
||||
testSet.tests.forEach(function (test) {
|
||||
// if (test.description != 'a single invalid match is invalid') return;
|
||||
// if (test.description != 'missing dependency') return;
|
||||
it(test.description, function() {
|
||||
var result = validate(test.data);
|
||||
// console.log('result', result);
|
||||
|
|
272
try.js
272
try.js
|
@ -1,215 +1,59 @@
|
|||
'use strict';
|
||||
validate = function(data, instance) {
|
||||
var self = this;
|
||||
var dataType = getDataType(data);
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var rule = RULES.properties;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var propertiesSchema = self.schema.properties;
|
||||
var pPropertiesSchema = self.schema.patternProperties,
|
||||
pPropertiesRegexps = {},
|
||||
dataKeysPPs;
|
||||
for (var pProperty in pPropertiesSchema) pPropertiesRegexps[pProperty] = new RegExp(pProperty);
|
||||
dataKeysPPs = {};
|
||||
for (var key in data) {
|
||||
var isAdditional = !propertiesSchema.hasOwnProperty(key);
|
||||
dataKeysPPs[key] = {};
|
||||
for (var pProperty in pPropertiesSchema) {
|
||||
var keyMatches = pPropertiesRegexps[pProperty].test(key);
|
||||
if (keyMatches) {
|
||||
dataKeysPPs[key][pProperty] = true;
|
||||
isAdditional = false;
|
||||
}
|
||||
}
|
||||
if (isAdditional) {
|
||||
var _data = data[key],
|
||||
_dataType = getDataType(_data),
|
||||
_dataPath = dataPath + '.' + key,
|
||||
result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var rule = RULES.type;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var valid;
|
||||
valid = dataType == 'number' && data === parseInt(data);
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'type',
|
||||
schema: 'integer',
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid. Expected integer',
|
||||
data: data
|
||||
}]
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(_data, _dataType, _dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.hasOwnProperty('foo')) {
|
||||
var _data = data['foo'],
|
||||
_dataType = getDataType(_data),
|
||||
_dataPath = dataPath + '.foo',
|
||||
result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var rule = RULES.type;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var valid;
|
||||
valid = dataType == 'array';
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'type',
|
||||
schema: 'array',
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid. Expected array',
|
||||
data: data
|
||||
}]
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
var rule = RULES.maxItems;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var valid = data.length <= 3;
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'maxItems',
|
||||
schema: 3,
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have more than 3 items',
|
||||
data: data
|
||||
}]
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(_data, _dataType, _dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
if (data.hasOwnProperty('bar')) {
|
||||
var _data = data['bar'],
|
||||
_dataType = getDataType(_data),
|
||||
_dataPath = dataPath + '.bar',
|
||||
result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var rule = RULES.type;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var valid;
|
||||
valid = dataType == 'array';
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'type',
|
||||
schema: 'array',
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid. Expected array',
|
||||
data: data
|
||||
}]
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(_data, _dataType, _dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
for (var key in data) {
|
||||
var keyMatches = dataKeysPPs[key]['f.o'];
|
||||
if (keyMatches) {
|
||||
var _data = data['f.o'],
|
||||
_dataType = getDataType(_data),
|
||||
_dataPath = dataPath + '.f.o',
|
||||
result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var errors = [];
|
||||
var rule = RULES.minItems;
|
||||
if (!rule.type || rule.type == dataType) {
|
||||
var result = (function(data, dataType, dataPath) {
|
||||
'use strict';
|
||||
var valid = data.length >= 2;
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'minItems',
|
||||
schema: 2,
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have less than 2 items',
|
||||
data: data
|
||||
}]
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(_data, _dataType, _dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(data, dataType, dataPath);
|
||||
if (!result.valid) {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: !errors.length,
|
||||
errors: errors
|
||||
};
|
||||
})(data, dataType, '');
|
||||
return result;
|
||||
var out = 'function (data, dataType, dataPath) { \'use strict\'; var errors = []; ';
|
||||
var $schemaDeps = {},
|
||||
$propertyDeps = {};
|
||||
for ($property in it.schema) {
|
||||
var $schema = it.schema[$property];
|
||||
var $deps = Array.isArray($schema) ? $propertyDeps : $schemaDeps;
|
||||
$deps[$property] = $schema;
|
||||
}
|
||||
out += ' ';
|
||||
for ($property in $propertyDeps) {
|
||||
out += ' if (data.hasOwnProperty(\'' + ($property) + '\')) { ';
|
||||
$deps = $propertyDeps[$property] out += ' var valid = ';
|
||||
var arr1 = $deps;
|
||||
if (arr1) {
|
||||
var $dep, $i = -1,
|
||||
l1 = arr1.length - 1;
|
||||
while ($i < l1) {
|
||||
$dep = arr1[$i += 1];
|
||||
if ($i) {
|
||||
out += ' || ';
|
||||
}
|
||||
out += 'data.hasOwnProperty(\'' + ($dep) + '\')';
|
||||
}
|
||||
}
|
||||
out += '; if (!valid) { var error = { keyword: \'dependencies\', schema: self.schema' + (it.schemaPath) + ', dataPath: dataPath, message: \'data\' + dataPath + \' is not valid, properties ' + ($deps.join(",")) + ' are required when property ' + ($property) + ' is present\' ';
|
||||
if (it.opts.verbose) {
|
||||
out += ', data: data';
|
||||
}
|
||||
out += ' } ';
|
||||
if (it.opts.allErrors) {
|
||||
out += ' errors.push(error); ';
|
||||
} else {
|
||||
out += ' return { valid: false, errors: [error] }; ';
|
||||
}
|
||||
out += ' } } ';
|
||||
}
|
||||
out += ' ';
|
||||
for ($property in $schemaDeps) {
|
||||
out += ' if (data.hasOwnProperty(\'' + ($property) + '\')) { ';
|
||||
var $schema = $schemaDeps[$property];
|
||||
var $it = it.copy(it);
|
||||
$it.schema = $schema;
|
||||
$it.schemaPath = it.schemaPath + '["' + it.escapeQuotes($property) + '"]';
|
||||
out += ' var result = (' + (it._validate($it)) + ')(data, dataType, dataPath); if (!result.valid) { ';
|
||||
if (it.opts.allErrors) {
|
||||
out += ' errors.push.apply(errors, result.errors); ';
|
||||
} else {
|
||||
out += ' return { valid: false, errors: result.errors }; ';
|
||||
}
|
||||
out += ' } } ';
|
||||
}
|
||||
out += ' ';
|
||||
if (it.opts.allErrors) {
|
||||
out += ' return { valid: !errors.length, errors: errors }; ';
|
||||
} else {
|
||||
out += ' return { valid: true, errors: [] }; ';
|
||||
}
|
||||
out += '}';
|
||||
return out;
|
||||
|
|
Loading…
Reference in New Issue