anyOf, enum, maxItems, minItems, maxLength, minLength, maxProperties, minProperties, multipleOf, oneOf, pattern rules
parent
008a93f447
commit
26abbd96d2
|
@ -1,7 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
var doT = require('dot')
|
||||
, fs = require('fs');
|
||||
, fs = require('fs')
|
||||
, stableStringify = require('json-stable-stringify');
|
||||
|
||||
var RULES = require('./rules')
|
||||
, _validateTemplateStr = fs.readFileSync(__dirname + '/_validate.dot.js')
|
||||
|
@ -19,6 +20,8 @@ function compile(schema) {
|
|||
RULES: RULES,
|
||||
_validate: _validateTemplate,
|
||||
copy: copy,
|
||||
getDataType: getDataType,
|
||||
stableStringify: stableStringify,
|
||||
opts: this.opts
|
||||
});
|
||||
// console.log('\n\n\n *** \n', validateCode);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var errors = [];
|
||||
|
||||
{{~ it.schema:$schema:$i }}
|
||||
{{
|
||||
var $it = it.copy(it);
|
||||
$it.schema = $schema;
|
||||
$it.schemaPath = it.schemaPath + '[' + $i + ']';
|
||||
}}
|
||||
|
||||
var result = ({{= it._validate($it) }})(data, dataType, dataPath);
|
||||
|
||||
if (result.valid) {
|
||||
return { valid: true, errors: [] };
|
||||
} else {
|
||||
errors.push.apply(errors, result.errors);
|
||||
}
|
||||
{{~}}
|
||||
|
||||
return { valid: false, errors: errors };
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var errors = [];
|
||||
|
||||
{{
|
||||
var $simpleTypes = [ 'boolean', 'null', 'number', 'string' ]
|
||||
, $itemsHash = { 'boolean': {}, 'null': {}, 'number': {}, 'string': {} };
|
||||
|
||||
var $onlySimpleTypes = it.schema.every(function ($item) {
|
||||
var $itemType = typeof $item;
|
||||
var $isSimpleType = $simpleTypes.indexOf($itemType) >= 0;
|
||||
if ($isSimpleType) $itemsHash[$itemType][$item] = true;
|
||||
return $isSimpleType;
|
||||
});
|
||||
|
||||
if (!$onlySimpleTypes) {
|
||||
var $itemsList = it.schema.map(function ($item) {
|
||||
return {
|
||||
type: it.getDataType($item),
|
||||
valueStr: it.stableStringify($item)
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
||||
{{? $onlySimpleTypes }}
|
||||
var itemsHash = {{= JSON.stringify($itemsHash) }};
|
||||
var valid = itemsHash[dataType] && itemsHash[dataType][data];
|
||||
{{??}}
|
||||
var itemsList = {{= JSON.stringify($itemsList) }};
|
||||
for (var i = 0; i < itemsList.length; i++) {
|
||||
var item = itemsList[i];
|
||||
var valid = dataType == item.type && stableStringify(data) == item.valueStr;
|
||||
if (valid) break;
|
||||
}
|
||||
{{?}}
|
||||
|
||||
return {
|
||||
valid: valid || false,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'enum',
|
||||
schema: self.schema{{= it.schemaPath }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should be equal to one of values in the schema'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -5,10 +5,10 @@ var fs = require('fs')
|
|||
|
||||
var RULES = module.exports = {
|
||||
type: { code: fs.readFileSync(__dirname + '/type.dot.js') },
|
||||
// enum: { code: '' },
|
||||
enum: { code: fs.readFileSync(__dirname + '/enum.dot.js') },
|
||||
allOf: { code: fs.readFileSync(__dirname + '/allOf.dot.js') },
|
||||
// anyOf: { code: '' },
|
||||
// oneOf: { code: '' },
|
||||
anyOf: { code: fs.readFileSync(__dirname + '/anyOf.dot.js') },
|
||||
oneOf: { code: fs.readFileSync(__dirname + '/oneOf.dot.js') },
|
||||
not: { code: fs.readFileSync(__dirname + '/not.dot.js') },
|
||||
maximum: {
|
||||
code: fs.readFileSync(__dirname + '/maximum.dot.js'),
|
||||
|
@ -18,22 +18,22 @@ var RULES = module.exports = {
|
|||
code: fs.readFileSync(__dirname + '/minimum.dot.js'),
|
||||
type: 'number'
|
||||
},
|
||||
// multipleOf: {
|
||||
// code: '',
|
||||
// type: 'number'
|
||||
// },
|
||||
// maxLength: {
|
||||
// code: '',
|
||||
// type: 'string'
|
||||
// },
|
||||
// minLength: {
|
||||
// code: '',
|
||||
// type: 'string'
|
||||
// },
|
||||
// pattern: {
|
||||
// code: '',
|
||||
// type: 'string'
|
||||
// },
|
||||
multipleOf: {
|
||||
code: fs.readFileSync(__dirname + '/multipleOf.dot.js'),
|
||||
type: 'number'
|
||||
},
|
||||
maxLength: {
|
||||
code: fs.readFileSync(__dirname + '/maxLength.dot.js'),
|
||||
type: 'string'
|
||||
},
|
||||
minLength: {
|
||||
code: fs.readFileSync(__dirname + '/minLength.dot.js'),
|
||||
type: 'string'
|
||||
},
|
||||
pattern: {
|
||||
code: fs.readFileSync(__dirname + '/pattern.dot.js'),
|
||||
type: 'string'
|
||||
},
|
||||
// additionalItems: {
|
||||
// code: '',
|
||||
// type: 'array'
|
||||
|
@ -42,26 +42,26 @@ var RULES = module.exports = {
|
|||
// code: '',
|
||||
// type: 'array'
|
||||
// },
|
||||
// maxItems: {
|
||||
// code: '',
|
||||
// type: 'array'
|
||||
// },
|
||||
// minItems: {
|
||||
// code: '',
|
||||
// type: 'array'
|
||||
// },
|
||||
maxItems: {
|
||||
code: fs.readFileSync(__dirname + '/maxItems.dot.js'),
|
||||
type: 'array'
|
||||
},
|
||||
minItems: {
|
||||
code: fs.readFileSync(__dirname + '/minItems.dot.js'),
|
||||
type: 'array'
|
||||
},
|
||||
// uniqueItems: {
|
||||
// code: '',
|
||||
// type: 'array'
|
||||
// },
|
||||
// maxProperties: {
|
||||
// code: '',
|
||||
// type: 'object'
|
||||
// },
|
||||
// minProperties: {
|
||||
// code: '',
|
||||
// type: 'object'
|
||||
// },
|
||||
maxProperties: {
|
||||
code: fs.readFileSync(__dirname + '/maxProperties.dot.js'),
|
||||
type: 'object'
|
||||
},
|
||||
minProperties: {
|
||||
code: fs.readFileSync(__dirname + '/minProperties.dot.js'),
|
||||
type: 'object'
|
||||
},
|
||||
required: {
|
||||
code: fs.readFileSync(__dirname + '/required.dot.js'),
|
||||
type: 'object'
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var valid = data.length <= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'maxItems',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have more than {{= it.schema }} items'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var valid = data.length <= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'maxLength',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT be longer than {{= it.schema }} characters'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var propertiesNum = Object.keys(data).length;
|
||||
var valid = propertiesNum <= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'maxProperties',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have more than {{= it.schema }} properties'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var valid = data.length >= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'minItems',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have less than {{= it.schema }} items'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var valid = data.length >= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'minLength',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT be shorter than {{= it.schema }} characters'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var propertiesNum = Object.keys(data).length;
|
||||
var valid = propertiesNum >= {{= it.schema }};
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'minProperties',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should NOT have less than {{= it.schema }} properties'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var division = data / {{= it.schema }};
|
||||
var valid = division === parseInt(division);
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'multipleOf',
|
||||
schema: {{= it.schema }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should be multiple of {{= it.schema }}'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var errors = [], foundValid = false;
|
||||
|
||||
{{~ it.schema:$schema:$i }}
|
||||
{{
|
||||
var $it = it.copy(it);
|
||||
$it.schema = $schema;
|
||||
$it.schemaPath = it.schemaPath + '[' + $i + ']';
|
||||
}}
|
||||
|
||||
var result = ({{= it._validate($it) }})(data, dataType, dataPath);
|
||||
|
||||
if (result.valid) {
|
||||
if (foundValid) return { valid: false, errors: [{
|
||||
keyword: 'oneOf',
|
||||
schema: self.schema{{= it.schemaPath }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' NOT valid, matches more that one schema in oneOf'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}] };
|
||||
foundValid = true;
|
||||
} else
|
||||
errors.push.apply(errors, result.errors);
|
||||
{{~}}
|
||||
|
||||
if (foundValid) errors = [];
|
||||
else errors.push({
|
||||
keyword: 'oneOf',
|
||||
schema: self.schema{{= it.schemaPath }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' NOT valid, matches none of the schemas in oneOf'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
});
|
||||
|
||||
return { valid: foundValid, errors: errors };
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
function (data, dataType, dataPath) {
|
||||
'use strict';
|
||||
|
||||
var valid = /{{= it.schema }}/.test(data);
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'minimum',
|
||||
schema: '{{= it.schema }}',
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, should match pattern "{{= it.schema }}"'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
|
@ -27,10 +27,10 @@ function (data, dataType, dataPath) {
|
|||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'required',
|
||||
schema: self.schema,
|
||||
schema: self.schema{{= it.schemaPath }},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid, properties ' + missing + ' are missing'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ function (data, dataType, dataPath) {
|
|||
valid: valid,
|
||||
errors: valid ? [] : [{
|
||||
keyword: 'type',
|
||||
schema: {{? $isArray }}self.schema{{= it.schemaPath }}{{??}}"{{= $schema }}"{{?}},
|
||||
schema: {{? $isArray }}self.schema{{= it.schemaPath }}{{??}}'{{= $schema }}'{{?}},
|
||||
dataPath: dataPath,
|
||||
message: 'data' + dataPath + ' is not valid. Expected {{? $isArray }}{{= $schema.join(",") }}{{??}}{{= $schema }}{{?}}'
|
||||
{{? it.opts.verbose }}, data: data{{?}}
|
||||
|
|
|
@ -6,8 +6,10 @@ var fs = require('fs')
|
|||
, TESTS_PATH = 'JSON-Schema-Test-Suite/tests/draft4/';
|
||||
|
||||
var ONLY_RULES;
|
||||
// ONLY_RULES = ['properties'];
|
||||
ONLY_RULES = ['type', 'not', 'maximum', 'minimum', 'allOf', 'properties', 'required'];
|
||||
// ONLY_RULES = ['maxItems', 'minItems'];
|
||||
// ONLY_RULES = ['type', 'not', 'maximum', 'minimum', 'allOf', 'anyOf', 'oneOf', 'enum',
|
||||
// 'properties', 'required', 'multipleOf', 'maxProperties', 'minProperties',
|
||||
// 'maxLength', 'minLength', 'pattern', 'maxItems', 'minItems'];
|
||||
|
||||
|
||||
var Jv = require('../lib/jv')
|
||||
|
@ -23,7 +25,7 @@ describe.only('JSON-Schema tests', function () {
|
|||
describe(file.name, function() {
|
||||
var testSets = require(file.path);
|
||||
testSets.forEach(function (testSet) {
|
||||
// if (testSet.description != 'not more complex schema') return;
|
||||
// if (testSet.description != 'oneOf') return;
|
||||
describe(testSet.description, function() {
|
||||
// it(testSet.description, function() {
|
||||
var validate, fullValidate;
|
||||
|
@ -33,15 +35,19 @@ describe.only('JSON-Schema tests', function () {
|
|||
});
|
||||
|
||||
testSet.tests.forEach(function (test) {
|
||||
// if (test.description != 'both properties present and valid is valid') return;
|
||||
// if (test.description != 'neither oneOf valid') return;
|
||||
it(test.description, function() {
|
||||
var result = validate(test.data);
|
||||
// console.log('result', result);
|
||||
assert.equal(result.valid, test.valid);
|
||||
if (result.valid) assert(result.errors.length == 0);
|
||||
else assert(result.errors.length > 0);
|
||||
|
||||
var result = fullValidate(test.data);
|
||||
// console.log('full result', result);
|
||||
assert.equal(result.valid, test.valid);
|
||||
if (result.valid) assert(result.errors.length == 0);
|
||||
else assert(result.errors.length > 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue