feat: allow refs to fragments in "getSchema" and "validate" methods, closes #47
parent
66dd12bc45
commit
2d9241a658
24
lib/ajv.js
24
lib/ajv.js
|
@ -39,6 +39,7 @@ function Ajv(opts) {
|
||||||
opts = this._opts = util.copy(opts) || {};
|
opts = this._opts = util.copy(opts) || {};
|
||||||
this._schemas = {};
|
this._schemas = {};
|
||||||
this._refs = {};
|
this._refs = {};
|
||||||
|
this._fragments = {};
|
||||||
this._formats = formats(opts.format);
|
this._formats = formats(opts.format);
|
||||||
this._cache = opts.cache || new Cache;
|
this._cache = opts.cache || new Cache;
|
||||||
this._loadingSchemas = {};
|
this._loadingSchemas = {};
|
||||||
|
@ -187,13 +188,34 @@ function Ajv(opts) {
|
||||||
switch (typeof schemaObj) {
|
switch (typeof schemaObj) {
|
||||||
case 'object': return schemaObj.validate || _compile(schemaObj);
|
case 'object': return schemaObj.validate || _compile(schemaObj);
|
||||||
case 'string': return getSchema(schemaObj);
|
case 'string': return getSchema(schemaObj);
|
||||||
|
case 'undefined': return _getSchemaFragment(keyRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _getSchemaFragment(ref) {
|
||||||
|
var res = resolve.schema.call(self, { schema: {} }, ref);
|
||||||
|
if (res) {
|
||||||
|
var schema = res.schema
|
||||||
|
, root = res.root
|
||||||
|
, baseId = res.baseId;
|
||||||
|
var v = compileSchema.call(self, schema, root, undefined, baseId);
|
||||||
|
self._fragments[ref] = new SchemaObject({
|
||||||
|
ref: ref,
|
||||||
|
fragment: true,
|
||||||
|
schema: schema,
|
||||||
|
root: root,
|
||||||
|
baseId: baseId,
|
||||||
|
validate: v
|
||||||
|
});
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function _getSchemaObj(keyRef) {
|
function _getSchemaObj(keyRef) {
|
||||||
keyRef = resolve.normalizeId(keyRef);
|
keyRef = resolve.normalizeId(keyRef);
|
||||||
return self._schemas[keyRef] || self._refs[keyRef];
|
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ resolve.fullPath = getFullPath;
|
||||||
resolve.url = resolveUrl;
|
resolve.url = resolveUrl;
|
||||||
resolve.ids = resolveIds;
|
resolve.ids = resolveIds;
|
||||||
resolve.inlineRef = inlineRef;
|
resolve.inlineRef = inlineRef;
|
||||||
|
resolve.schema = resolveSchema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [resolve and compile the references ($ref)]
|
* [resolve and compile the references ($ref)]
|
||||||
|
@ -36,7 +37,7 @@ function resolve(compile, root, ref) {
|
||||||
: refVal.validate || this._compile(refVal);
|
: refVal.validate || this._compile(refVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = _resolve.call(this, root, ref);
|
var res = resolveSchema.call(this, root, ref);
|
||||||
var schema, v, baseId;
|
var schema, v, baseId;
|
||||||
if (res) {
|
if (res) {
|
||||||
schema = res.schema;
|
schema = res.schema;
|
||||||
|
@ -56,8 +57,14 @@ function resolve(compile, root, ref) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* @this Ajv */
|
/**
|
||||||
function _resolve(root, ref) {
|
* Resolve schema, its root and baseId
|
||||||
|
* @this Ajv
|
||||||
|
* @param {Object} root root object with properties schema, refVal, refs
|
||||||
|
* @param {String} ref reference to resolve
|
||||||
|
* @return {Object} object with properties schema, root, baseId
|
||||||
|
*/
|
||||||
|
function resolveSchema(root, ref) {
|
||||||
/* jshint validthis: true */
|
/* jshint validthis: true */
|
||||||
var p = url.parse(ref, false, true)
|
var p = url.parse(ref, false, true)
|
||||||
, refPath = _getFullPath(p)
|
, refPath = _getFullPath(p)
|
||||||
|
@ -91,7 +98,7 @@ function _resolve(root, ref) {
|
||||||
/* @this Ajv */
|
/* @this Ajv */
|
||||||
function resolveRecursive(root, ref, parsedRef) {
|
function resolveRecursive(root, ref, parsedRef) {
|
||||||
/* jshint validthis: true */
|
/* jshint validthis: true */
|
||||||
var res = _resolve.call(this, root, ref);
|
var res = resolveSchema.call(this, root, ref);
|
||||||
if (res) {
|
if (res) {
|
||||||
var schema = res.schema;
|
var schema = res.schema;
|
||||||
var baseId = res.baseId;
|
var baseId = res.baseId;
|
||||||
|
@ -119,7 +126,7 @@ function getJsonPointer(parsedRef, baseId, schema, root) {
|
||||||
if (schema.id && !PREVENT_SCOPE_CHANGE[part]) baseId = resolveUrl(baseId, schema.id);
|
if (schema.id && !PREVENT_SCOPE_CHANGE[part]) baseId = resolveUrl(baseId, schema.id);
|
||||||
if (schema.$ref) {
|
if (schema.$ref) {
|
||||||
var $ref = resolveUrl(baseId, schema.$ref);
|
var $ref = resolveUrl(baseId, schema.$ref);
|
||||||
var res = _resolve.call(this, root, $ref);
|
var res = resolveSchema.call(this, root, $ref);
|
||||||
if (res) {
|
if (res) {
|
||||||
schema = res.schema;
|
schema = res.schema;
|
||||||
root = res.root;
|
root = res.root;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ajv",
|
"name": "ajv",
|
||||||
"version": "4.4.1",
|
"version": "4.5.0",
|
||||||
"description": "Another JSON Schema Validator",
|
"description": "Another JSON Schema Validator",
|
||||||
"main": "lib/ajv.js",
|
"main": "lib/ajv.js",
|
||||||
"typings": "lib/ajv.d.ts",
|
"typings": "lib/ajv.d.ts",
|
||||||
|
|
|
@ -88,6 +88,32 @@ describe('Ajv', function () {
|
||||||
ajv.validate('integer', 1) .should.equal(true);
|
ajv.validate('integer', 1) .should.equal(true);
|
||||||
should.throw(function() { ajv.validate('string', 'foo'); });
|
should.throw(function() { ajv.validate('string', 'foo'); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should validate schema fragment by ref', function() {
|
||||||
|
ajv.addSchema({
|
||||||
|
"id": "http://e.com/types.json",
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" },
|
||||||
|
"str": { "type": "string" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.validate('http://e.com/types.json#/definitions/int', 1) .should.equal(true);
|
||||||
|
ajv.validate('http://e.com/types.json#/definitions/int', '1') .should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return schema fragment by id', function() {
|
||||||
|
ajv.addSchema({
|
||||||
|
"id": "http://e.com/types.json",
|
||||||
|
"definitions": {
|
||||||
|
"int": { "id": "#int", "type": "integer" },
|
||||||
|
"str": { "id": "#str", "type": "string" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.validate('http://e.com/types.json#int', 1) .should.equal(true);
|
||||||
|
ajv.validate('http://e.com/types.json#int', '1') .should.equal(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,6 +236,34 @@ describe('Ajv', function () {
|
||||||
v(1) .should.equal(true);
|
v(1) .should.equal(true);
|
||||||
v('1') .should.equal(false);
|
v('1') .should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return schema fragment by ref', function() {
|
||||||
|
ajv.addSchema({
|
||||||
|
"id": "http://e.com/types.json",
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" },
|
||||||
|
"str": { "type": "string" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var vInt = ajv.getSchema('http://e.com/types.json#/definitions/int');
|
||||||
|
vInt(1) .should.equal(true);
|
||||||
|
vInt('1') .should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return schema fragment by id', function() {
|
||||||
|
ajv.addSchema({
|
||||||
|
"id": "http://e.com/types.json",
|
||||||
|
"definitions": {
|
||||||
|
"int": { "id": "#int", "type": "integer" },
|
||||||
|
"str": { "id": "#str", "type": "string" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var vInt = ajv.getSchema('http://e.com/types.json#int');
|
||||||
|
vInt(1) .should.equal(true);
|
||||||
|
vInt('1') .should.equal(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue