Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * json-schema-draft-01 Environment
- *
- * @fileOverview Implementation of the first revision of the JSON Schema specification draft.
- * @author <a href="mailto:[email protected]">Gary Court</a>
- * @version 1.7.1
- * @see http://github.com/garycourt/JSV
- */
- /*
- * Copyright 2010 Gary Court. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Gary Court or the JSON Schema specification.
- */
- /*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */
- /*global require */
- (function () {
- var O = {},
- JSV = require('./jsv').JSV,
- ENVIRONMENT,
- TYPE_VALIDATORS,
- SCHEMA,
- HYPERSCHEMA,
- LINKS;
- TYPE_VALIDATORS = {
- "string" : function (instance, report) {
- return instance.getType() === "string";
- },
- "number" : function (instance, report) {
- return instance.getType() === "number";
- },
- "integer" : function (instance, report) {
- return instance.getType() === "number" && instance.getValue() % 1 === 0;
- },
- "boolean" : function (instance, report) {
- return instance.getType() === "boolean";
- },
- "object" : function (instance, report) {
- return instance.getType() === "object";
- },
- "array" : function (instance, report) {
- return instance.getType() === "array";
- },
- "null" : function (instance, report) {
- return instance.getType() === "null";
- },
- "any" : function (instance, report) {
- return true;
- }
- };
- ENVIRONMENT = new JSV.Environment();
- ENVIRONMENT.setOption("defaultFragmentDelimiter", ".");
- ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/schema#"); //updated later
- SCHEMA = ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/schema#",
- "type" : "object",
- "properties" : {
- "type" : {
- "type" : ["string", "array"],
- "items" : {
- "type" : ["string", {"$ref" : "#"}]
- },
- "optional" : true,
- "uniqueItems" : true,
- "default" : "any",
- "parser" : function (instance, self) {
- var parser;
- if (instance.getType() === "string") {
- return instance.getValue();
- } else if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(
- instance,
- self.getEnvironment().findSchema(self.resolveURI("#"))
- );
- } else if (instance.getType() === "array") {
- parser = self.getValueOfProperty("parser");
- return JSV.mapArray(instance.getProperties(), function (prop) {
- return parser(prop, self);
- });
- }
- //else
- return "any";
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var requiredTypes = JSV.toArray(schema.getAttribute("type")),
- x, xl, type, subreport, typeValidators;
- //for instances that are required to be a certain type
- if (instance.getType() !== "undefined" && requiredTypes && requiredTypes.length) {
- typeValidators = self.getValueOfProperty("typeValidators") || {};
- //ensure that type matches for at least one of the required types
- for (x = 0, xl = requiredTypes.length; x < xl; ++x) {
- type = requiredTypes[x];
- if (JSV.isJSONSchema(type)) {
- subreport = JSV.createObject(report);
- subreport.errors = [];
- subreport.validated = JSV.clone(report.validated);
- if (type.validate(instance, subreport, parent, parentSchema, name).errors.length === 0) {
- return true; //instance matches this schema
- }
- } else {
- if (typeValidators[type] !== O[type] && typeof typeValidators[type] === "function") {
- if (typeValidators[type](instance, report)) {
- return true; //type is valid
- }
- } else {
- return true; //unknown types are assumed valid
- }
- }
- }
- //if we get to this point, type is invalid
- report.addError(instance, schema, "type", "Instance is not a required type", requiredTypes);
- return false;
- }
- //else, anything is allowed if no type is specified
- return true;
- },
- "typeValidators" : TYPE_VALIDATORS
- },
- "properties" : {
- "type" : "object",
- "additionalProperties" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self, arg) {
- var env = instance.getEnvironment(),
- selfEnv = self.getEnvironment();
- if (instance.getType() === "object") {
- if (arg) {
- return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI("#")));
- } else {
- return JSV.mapObject(instance.getProperties(), function (instance) {
- return env.createSchema(instance, selfEnv.findSchema(self.resolveURI("#")));
- });
- }
- }
- //else
- return {};
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var propertySchemas, key;
- //this attribute is for object type instances only
- if (instance.getType() === "object") {
- //for each property defined in the schema
- propertySchemas = schema.getAttribute("properties");
- for (key in propertySchemas) {
- if (propertySchemas[key] !== O[key] && propertySchemas[key]) {
- //ensure that instance property is valid
- propertySchemas[key].validate(instance.getProperty(key), report, instance, schema, key);
- }
- }
- }
- }
- },
- "items" : {
- "type" : [{"$ref" : "#"}, "array"],
- "items" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "array") {
- return JSV.mapArray(instance.getProperties(), function (instance) {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- });
- }
- //else
- return instance.getEnvironment().createEmptySchema();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var properties, items, x, xl, itemSchema, additionalProperties;
- if (instance.getType() === "array") {
- properties = instance.getProperties();
- items = schema.getAttribute("items");
- additionalProperties = schema.getAttribute("additionalProperties");
- if (JSV.typeOf(items) === "array") {
- for (x = 0, xl = properties.length; x < xl; ++x) {
- itemSchema = items[x] || additionalProperties;
- if (itemSchema !== false) {
- itemSchema.validate(properties[x], report, instance, schema, x);
- } else {
- report.addError(instance, schema, "additionalProperties", "Additional items are not allowed", itemSchema);
- }
- }
- } else {
- itemSchema = items || additionalProperties;
- for (x = 0, xl = properties.length; x < xl; ++x) {
- itemSchema.validate(properties[x], report, instance, schema, x);
- }
- }
- }
- }
- },
- "optional" : {
- "type" : "boolean",
- "optional" : true,
- "default" : true,
- "parser" : function (instance, self) {
- return !!instance.getValue();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- if (instance.getType() === "undefined" && !schema.getAttribute("optional")) {
- report.addError(instance, schema, "optional", "Property is required", false);
- }
- },
- "validationRequired" : true
- },
- "additionalProperties" : {
- "type" : [{"$ref" : "#"}, "boolean"],
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "boolean" && instance.getValue() === false) {
- return false;
- }
- //else
- return instance.getEnvironment().createEmptySchema();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var additionalProperties, propertySchemas, properties, key;
- //we only need to check against object types as arrays do their own checking on this property
- if (instance.getType() === "object") {
- additionalProperties = schema.getAttribute("additionalProperties");
- propertySchemas = schema.getAttribute("properties") || {};
- properties = instance.getProperties();
- for (key in properties) {
- if (properties[key] !== O[key] && properties[key] && !propertySchemas[key]) {
- if (JSV.isJSONSchema(additionalProperties)) {
- additionalProperties.validate(properties[key], report, instance, schema, key);
- } else if (additionalProperties === false) {
- report.addError(instance, schema, "additionalProperties", "Additional properties are not allowed", additionalProperties);
- }
- }
- }
- }
- }
- },
- "requires" : {
- "type" : ["string", {"$ref" : "#"}],
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- } else if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var requires;
- if (instance.getType() !== "undefined" && parent && parent.getType() !== "undefined") {
- requires = schema.getAttribute("requires");
- if (typeof requires === "string") {
- if (parent.getProperty(requires).getType() === "undefined") {
- report.addError(instance, schema, "requires", 'Property requires sibling property "' + requires + '"', requires);
- }
- } else if (JSV.isJSONSchema(requires)) {
- requires.validate(parent, report); //WATCH: A "requires" schema does not support the "requires" attribute
- }
- }
- }
- },
- "minimum" : {
- "type" : "number",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minimum, minimumCanEqual;
- if (instance.getType() === "number") {
- minimum = schema.getAttribute("minimum");
- minimumCanEqual = schema.getAttribute("minimumCanEqual");
- if (typeof minimum === "number" && (instance.getValue() < minimum || (minimumCanEqual === false && instance.getValue() === minimum))) {
- report.addError(instance, schema, "minimum", "Number is less than the required minimum value", minimum);
- }
- }
- }
- },
- "maximum" : {
- "type" : "number",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maximum, maximumCanEqual;
- if (instance.getType() === "number") {
- maximum = schema.getAttribute("maximum");
- maximumCanEqual = schema.getAttribute("maximumCanEqual");
- if (typeof maximum === "number" && (instance.getValue() > maximum || (maximumCanEqual === false && instance.getValue() === maximum))) {
- report.addError(instance, schema, "maximum", "Number is greater than the required maximum value", maximum);
- }
- }
- }
- },
- "minimumCanEqual" : {
- "type" : "boolean",
- "optional" : true,
- "requires" : "minimum",
- "default" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "boolean") {
- return instance.getValue();
- }
- //else
- return true;
- }
- },
- "maximumCanEqual" : {
- "type" : "boolean",
- "optional" : true,
- "requires" : "maximum",
- "default" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "boolean") {
- return instance.getValue();
- }
- //else
- return true;
- }
- },
- "minItems" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "default" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- //else
- return 0;
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minItems;
- if (instance.getType() === "array") {
- minItems = schema.getAttribute("minItems");
- if (typeof minItems === "number" && instance.getProperties().length < minItems) {
- report.addError(instance, schema, "minItems", "The number of items is less than the required minimum", minItems);
- }
- }
- }
- },
- "maxItems" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maxItems;
- if (instance.getType() === "array") {
- maxItems = schema.getAttribute("maxItems");
- if (typeof maxItems === "number" && instance.getProperties().length > maxItems) {
- report.addError(instance, schema, "maxItems", "The number of items is greater than the required maximum", maxItems);
- }
- }
- }
- },
- "pattern" : {
- "type" : "string",
- "optional" : true,
- "format" : "regex",
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var pattern;
- try {
- pattern = new RegExp(schema.getAttribute("pattern"));
- if (instance.getType() === "string" && pattern && !pattern.test(instance.getValue())) {
- report.addError(instance, schema, "pattern", "String does not match pattern", pattern.toString());
- }
- } catch (e) {
- report.addError(instance, schema, "pattern", "Invalid pattern", e);
- }
- }
- },
- "minLength" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "default" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- //else
- return 0;
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minLength;
- if (instance.getType() === "string") {
- minLength = schema.getAttribute("minLength");
- if (typeof minLength === "number" && instance.getValue().length < minLength) {
- report.addError(instance, schema, "minLength", "String is less than the required minimum length", minLength);
- }
- }
- }
- },
- "maxLength" : {
- "type" : "integer",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maxLength;
- if (instance.getType() === "string") {
- maxLength = schema.getAttribute("maxLength");
- if (typeof maxLength === "number" && instance.getValue().length > maxLength) {
- report.addError(instance, schema, "maxLength", "String is greater than the required maximum length", maxLength);
- }
- }
- }
- },
- "enum" : {
- "type" : "array",
- "optional" : true,
- "minItems" : 1,
- "uniqueItems" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "array") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var enums, x, xl;
- if (instance.getType() !== "undefined") {
- enums = schema.getAttribute("enum");
- if (enums) {
- for (x = 0, xl = enums.length; x < xl; ++x) {
- if (instance.equals(enums[x])) {
- return true;
- }
- }
- report.addError(instance, schema, "enum", "Instance is not one of the possible values", enums);
- }
- }
- }
- },
- "title" : {
- "type" : "string",
- "optional" : true
- },
- "description" : {
- "type" : "string",
- "optional" : true
- },
- "format" : {
- "type" : "string",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var format, formatValidators;
- if (instance.getType() === "string") {
- format = schema.getAttribute("format");
- formatValidators = self.getValueOfProperty("formatValidators");
- if (typeof format === "string" && formatValidators[format] !== O[format] && typeof formatValidators[format] === "function" && !formatValidators[format].call(this, instance, report)) {
- report.addError(instance, schema, "format", "String is not in the required format", format);
- }
- }
- },
- "formatValidators" : {}
- },
- "contentEncoding" : {
- "type" : "string",
- "optional" : true
- },
- "default" : {
- "type" : "any",
- "optional" : true
- },
- "maxDecimal" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maxDecimal, decimals;
- if (instance.getType() === "number") {
- maxDecimal = schema.getAttribute("maxDecimal");
- if (typeof maxDecimal === "number") {
- decimals = instance.getValue().toString(10).split('.')[1];
- if (decimals && decimals.length > maxDecimal) {
- report.addError(instance, schema, "maxDecimal", "The number of decimal places is greater than the allowed maximum", maxDecimal);
- }
- }
- }
- }
- },
- "disallow" : {
- "type" : ["string", "array"],
- "items" : {"type" : "string"},
- "optional" : true,
- "uniqueItems" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string" || instance.getType() === "array") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var disallowedTypes = JSV.toArray(schema.getAttribute("disallow")),
- x, xl, key, typeValidators;
- //for instances that are required to be a certain type
- if (instance.getType() !== "undefined" && disallowedTypes && disallowedTypes.length) {
- typeValidators = self.getValueOfProperty("typeValidators") || {};
- //ensure that type matches for at least one of the required types
- for (x = 0, xl = disallowedTypes.length; x < xl; ++x) {
- key = disallowedTypes[x];
- if (typeValidators[key] !== O[key] && typeof typeValidators[key] === "function") {
- if (typeValidators[key](instance, report)) {
- report.addError(instance, schema, "disallow", "Instance is a disallowed type", disallowedTypes);
- return 8;
- }
- }
- /*
- else {
- report.addError(instance, schema, "disallow", "Instance may be a disallowed type", disallowedTypes);
- return false;
- }
- */
- }
- //if we get to this point, type is valid
- return true;
- }
- //else, everything is allowed if no disallowed types are specified
- return true;
- },
- "typeValidators" : TYPE_VALIDATORS
- },
- "extends" : {
- "type" : [{"$ref" : "#"}, "array"],
- "items" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "array") {
- return JSV.mapArray(instance.getProperties(), function (instance) {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- });
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var extensions = schema.getAttribute("extends"), x, xl;
- if (extensions) {
- if (JSV.isJSONSchema(extensions)) {
- extensions.validate(instance, report, parent, parentSchema, name);
- } else if (JSV.typeOf(extensions) === "array") {
- for (x = 0, xl = extensions.length; x < xl; ++x) {
- extensions[x].validate(instance, report, parent, parentSchema, name);
- }
- }
- }
- }
- }
- },
- "optional" : true,
- "default" : {},
- "fragmentResolution" : "dot-delimited",
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self);
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var propNames = schema.getPropertyNames(),
- x, xl,
- attributeSchemas = self.getAttribute("properties"),
- validator;
- for (x in attributeSchemas) {
- if (attributeSchemas[x] !== O[x] && attributeSchemas[x].getValueOfProperty("validationRequired")) {
- JSV.pushUnique(propNames, x);
- }
- }
- for (x = 0, xl = propNames.length; x < xl; ++x) {
- if (attributeSchemas[propNames[x]] !== O[propNames[x]]) {
- validator = attributeSchemas[propNames[x]].getValueOfProperty("validator");
- if (typeof validator === "function") {
- validator(instance, schema, attributeSchemas[propNames[x]], report, parent, parentSchema, name);
- }
- }
- }
- },
- "initializer" : function (instance) {
- var link, extension, extended;
- //if there is a link to a different schema, set reference
- link = instance._schema.getLink("describedby", instance);
- if (link && instance._schema._uri !== link) {
- instance.setReference("describedby", link);
- }
- //if instance has a URI link to itself, update it's own URI
- link = instance._schema.getLink("self", instance);
- if (JSV.typeOf(link) === "string") {
- instance._uri = JSV.formatURI(link);
- }
- //if there is a link to the full representation, set reference
- link = instance._schema.getLink("full", instance);
- if (link && instance._uri !== link) {
- instance.setReference("full", link);
- }
- //extend schema
- extension = instance.getAttribute("extends");
- if (JSV.isJSONSchema(extension)) {
- extended = JSV.inherits(extension, instance, true);
- instance = instance._env.createSchema(extended, instance._schema, instance._uri);
- }
- return instance;
- }
- }, true, "http://json-schema.org/schema#");
- HYPERSCHEMA = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA, ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/hyper-schema#",
- "properties" : {
- "links" : {
- "type" : "array",
- "items" : {"$ref" : "links#"},
- "optional" : true,
- "parser" : function (instance, self, arg) {
- var links,
- linkSchemaURI = self.getValueOfProperty("items")["$ref"],
- linkSchema = self.getEnvironment().findSchema(linkSchemaURI),
- linkParser = linkSchema && linkSchema.getValueOfProperty("parser");
- arg = JSV.toArray(arg);
- if (typeof linkParser === "function") {
- links = JSV.mapArray(instance.getProperties(), function (link) {
- return linkParser(link, linkSchema);
- });
- } else {
- links = JSV.toArray(instance.getValue());
- }
- if (arg[0]) {
- links = JSV.filterArray(links, function (link) {
- return link["rel"] === arg[0];
- });
- }
- if (arg[1]) {
- links = JSV.mapArray(links, function (link) {
- var instance = arg[1],
- href = link["href"];
- href = href.replace(/\{(.+)\}/g, function (str, p1, offset, s) {
- var value;
- if (p1 === "-this") {
- value = instance.getValue();
- } else {
- value = instance.getValueOfProperty(p1);
- }
- return value !== undefined ? String(value) : "";
- });
- return href ? JSV.formatURI(instance.resolveURI(href)) : href;
- });
- }
- return links;
- }
- },
- "fragmentResolution" : {
- "type" : "string",
- "optional" : true,
- "default" : "dot-delimited"
- },
- "root" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false
- },
- "readonly" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false
- },
- "pathStart" : {
- "type" : "string",
- "optional" : true,
- "format" : "uri",
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var pathStart;
- if (instance.getType() !== "undefined") {
- pathStart = schema.getAttribute("pathStart");
- if (typeof pathStart === "string") {
- //TODO: Find out what pathStart is relative to
- if (instance.getURI().indexOf(pathStart) !== 0) {
- report.addError(instance, schema, "pathStart", "Instance's URI does not start with " + pathStart, pathStart);
- }
- }
- }
- }
- },
- "mediaType" : {
- "type" : "string",
- "optional" : true,
- "format" : "media-type"
- },
- "alternate" : {
- "type" : "array",
- "items" : {"$ref" : "#"},
- "optional" : true
- }
- },
- "links" : [
- {
- "href" : "{$ref}",
- "rel" : "full"
- },
- {
- "href" : "{$schema}",
- "rel" : "describedby"
- },
- {
- "href" : "{id}",
- "rel" : "self"
- }
- ]//,
- //not needed as JSV.inherits does the job for us
- //"extends" : {"$ref" : "http://json-schema.org/schema#"}
- }, SCHEMA), true), true, "http://json-schema.org/hyper-schema#");
- ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/hyper-schema#");
- LINKS = ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/links#",
- "type" : "object",
- "properties" : {
- "href" : {
- "type" : "string"
- },
- "rel" : {
- "type" : "string"
- },
- "method" : {
- "type" : "string",
- "default" : "GET",
- "optional" : true
- },
- "enctype" : {
- "type" : "string",
- "requires" : "method",
- "optional" : true
- },
- "properties" : {
- "type" : "object",
- "additionalProperties" : {"$ref" : "hyper-schema#"},
- "optional" : true,
- "parser" : function (instance, self, arg) {
- var env = instance.getEnvironment(),
- selfEnv = self.getEnvironment(),
- additionalPropertiesSchemaURI = self.getValueOfProperty("additionalProperties")["$ref"];
- if (instance.getType() === "object") {
- if (arg) {
- return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
- } else {
- return JSV.mapObject(instance.getProperties(), function (instance) {
- return env.createSchema(instance, selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
- });
- }
- }
- }
- }
- },
- "parser" : function (instance, self) {
- var selfProperties = self.getProperty("properties");
- if (instance.getType() === "object") {
- return JSV.mapObject(instance.getProperties(), function (property, key) {
- var propertySchema = selfProperties.getProperty(key),
- parser = propertySchema && propertySchema.getValueOfProperty("parser");
- if (typeof parser === "function") {
- return parser(property, propertySchema);
- }
- //else
- return property.getValue();
- });
- }
- return instance.getValue();
- }
- }, HYPERSCHEMA, "http://json-schema.org/links#");
- JSV.registerEnvironment("json-schema-draft-00", ENVIRONMENT);
- JSV.registerEnvironment("json-schema-draft-01", JSV.createEnvironment("json-schema-draft-00"));
- if (!JSV.getDefaultEnvironmentID()) {
- JSV.setDefaultEnvironmentID("json-schema-draft-01");
- }
- }());
- /////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * json-schema-draft-02 Environment
- *
- * @fileOverview Implementation of the second revision of the JSON Schema specification draft.
- * @author <a href="mailto:[email protected]">Gary Court</a>
- * @version 1.7.1
- * @see http://github.com/garycourt/JSV
- */
- /*
- * Copyright 2010 Gary Court. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of Gary Court or the JSON Schema specification.
- */
- /*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */
- /*global require */
- (function () {
- var O = {},
- JSV = require('./jsv').JSV,
- ENVIRONMENT,
- TYPE_VALIDATORS,
- SCHEMA,
- HYPERSCHEMA,
- LINKS;
- TYPE_VALIDATORS = {
- "string" : function (instance, report) {
- return instance.getType() === "string";
- },
- "number" : function (instance, report) {
- return instance.getType() === "number";
- },
- "integer" : function (instance, report) {
- return instance.getType() === "number" && instance.getValue() % 1 === 0;
- },
- "boolean" : function (instance, report) {
- return instance.getType() === "boolean";
- },
- "object" : function (instance, report) {
- return instance.getType() === "object";
- },
- "array" : function (instance, report) {
- return instance.getType() === "array";
- },
- "null" : function (instance, report) {
- return instance.getType() === "null";
- },
- "any" : function (instance, report) {
- return true;
- }
- };
- ENVIRONMENT = new JSV.Environment();
- ENVIRONMENT.setOption("defaultFragmentDelimiter", "/");
- ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/schema#"); //updated later
- SCHEMA = ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/schema#",
- "type" : "object",
- "properties" : {
- "type" : {
- "type" : ["string", "array"],
- "items" : {
- "type" : ["string", {"$ref" : "#"}]
- },
- "optional" : true,
- "uniqueItems" : true,
- "default" : "any",
- "parser" : function (instance, self) {
- var parser;
- if (instance.getType() === "string") {
- return instance.getValue();
- } else if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(
- instance,
- self.getEnvironment().findSchema(self.resolveURI("#"))
- );
- } else if (instance.getType() === "array") {
- parser = self.getValueOfProperty("parser");
- return JSV.mapArray(instance.getProperties(), function (prop) {
- return parser(prop, self);
- });
- }
- //else
- return "any";
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var requiredTypes = JSV.toArray(schema.getAttribute("type")),
- x, xl, type, subreport, typeValidators;
- //for instances that are required to be a certain type
- if (instance.getType() !== "undefined" && requiredTypes && requiredTypes.length) {
- typeValidators = self.getValueOfProperty("typeValidators") || {};
- //ensure that type matches for at least one of the required types
- for (x = 0, xl = requiredTypes.length; x < xl; ++x) {
- type = requiredTypes[x];
- if (JSV.isJSONSchema(type)) {
- subreport = JSV.createObject(report);
- subreport.errors = [];
- subreport.validated = JSV.clone(report.validated);
- if (type.validate(instance, subreport, parent, parentSchema, name).errors.length === 0) {
- return true; //instance matches this schema
- }
- } else {
- if (typeValidators[type] !== O[type] && typeof typeValidators[type] === "function") {
- if (typeValidators[type](instance, report)) {
- return true; //type is valid
- }
- } else {
- return true; //unknown types are assumed valid
- }
- }
- }
- //if we get to this point, type is invalid
- report.addError(instance, schema, "type", "Instance is not a required type", requiredTypes);
- return false;
- }
- //else, anything is allowed if no type is specified
- return true;
- },
- "typeValidators" : TYPE_VALIDATORS
- },
- "properties" : {
- "type" : "object",
- "additionalProperties" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self, arg) {
- var env = instance.getEnvironment(),
- selfEnv = self.getEnvironment();
- if (instance.getType() === "object") {
- if (arg) {
- return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI("#")));
- } else {
- return JSV.mapObject(instance.getProperties(), function (instance) {
- return env.createSchema(instance, selfEnv.findSchema(self.resolveURI("#")));
- });
- }
- }
- //else
- return {};
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var propertySchemas, key;
- //this attribute is for object type instances only
- if (instance.getType() === "object") {
- //for each property defined in the schema
- propertySchemas = schema.getAttribute("properties");
- for (key in propertySchemas) {
- if (propertySchemas[key] !== O[key] && propertySchemas[key]) {
- //ensure that instance property is valid
- propertySchemas[key].validate(instance.getProperty(key), report, instance, schema, key);
- }
- }
- }
- }
- },
- "items" : {
- "type" : [{"$ref" : "#"}, "array"],
- "items" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "array") {
- return JSV.mapArray(instance.getProperties(), function (instance) {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- });
- }
- //else
- return instance.getEnvironment().createEmptySchema();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var properties, items, x, xl, itemSchema, additionalProperties;
- if (instance.getType() === "array") {
- properties = instance.getProperties();
- items = schema.getAttribute("items");
- additionalProperties = schema.getAttribute("additionalProperties");
- if (JSV.typeOf(items) === "array") {
- for (x = 0, xl = properties.length; x < xl; ++x) {
- itemSchema = items[x] || additionalProperties;
- if (itemSchema !== false) {
- itemSchema.validate(properties[x], report, instance, schema, x);
- } else {
- report.addError(instance, schema, "additionalProperties", "Additional items are not allowed", itemSchema);
- }
- }
- } else {
- itemSchema = items || additionalProperties;
- for (x = 0, xl = properties.length; x < xl; ++x) {
- itemSchema.validate(properties[x], report, instance, schema, x);
- }
- }
- }
- }
- },
- "optional" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false,
- "parser" : function (instance, self) {
- return !!instance.getValue();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- if (instance.getType() === "undefined" && !schema.getAttribute("optional")) {
- report.addError(instance, schema, "optional", "Property is required", false);
- }
- },
- "validationRequired" : true
- },
- "additionalProperties" : {
- "type" : [{"$ref" : "#"}, "boolean"],
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "boolean" && instance.getValue() === false) {
- return false;
- }
- //else
- return instance.getEnvironment().createEmptySchema();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var additionalProperties, propertySchemas, properties, key;
- //we only need to check against object types as arrays do their own checking on this property
- if (instance.getType() === "object") {
- additionalProperties = schema.getAttribute("additionalProperties");
- propertySchemas = schema.getAttribute("properties") || {};
- properties = instance.getProperties();
- for (key in properties) {
- if (properties[key] !== O[key] && properties[key] && !propertySchemas[key]) {
- if (JSV.isJSONSchema(additionalProperties)) {
- additionalProperties.validate(properties[key], report, instance, schema, key);
- } else if (additionalProperties === false) {
- report.addError(instance, schema, "additionalProperties", "Additional properties are not allowed", additionalProperties);
- }
- }
- }
- }
- }
- },
- "requires" : {
- "type" : ["string", {"$ref" : "#"}],
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- } else if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var requires;
- if (instance.getType() !== "undefined" && parent && parent.getType() !== "undefined") {
- requires = schema.getAttribute("requires");
- if (typeof requires === "string") {
- if (parent.getProperty(requires).getType() === "undefined") {
- report.addError(instance, schema, "requires", 'Property requires sibling property "' + requires + '"', requires);
- }
- } else if (JSV.isJSONSchema(requires)) {
- requires.validate(parent, report); //WATCH: A "requires" schema does not support the "requires" attribute
- }
- }
- }
- },
- "minimum" : {
- "type" : "number",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minimum, minimumCanEqual;
- if (instance.getType() === "number") {
- minimum = schema.getAttribute("minimum");
- minimumCanEqual = schema.getAttribute("minimumCanEqual");
- if (typeof minimum === "number" && (instance.getValue() < minimum || (minimumCanEqual === false && instance.getValue() === minimum))) {
- report.addError(instance, schema, "minimum", "Number is less than the required minimum value", minimum);
- }
- }
- }
- },
- "maximum" : {
- "type" : "number",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maximum, maximumCanEqual;
- if (instance.getType() === "number") {
- maximum = schema.getAttribute("maximum");
- maximumCanEqual = schema.getAttribute("maximumCanEqual");
- if (typeof maximum === "number" && (instance.getValue() > maximum || (maximumCanEqual === false && instance.getValue() === maximum))) {
- report.addError(instance, schema, "maximum", "Number is greater than the required maximum value", maximum);
- }
- }
- }
- },
- "minimumCanEqual" : {
- "type" : "boolean",
- "optional" : true,
- "requires" : "minimum",
- "default" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "boolean") {
- return instance.getValue();
- }
- //else
- return true;
- }
- },
- "maximumCanEqual" : {
- "type" : "boolean",
- "optional" : true,
- "requires" : "maximum",
- "default" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "boolean") {
- return instance.getValue();
- }
- //else
- return true;
- }
- },
- "minItems" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "default" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- //else
- return 0;
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minItems;
- if (instance.getType() === "array") {
- minItems = schema.getAttribute("minItems");
- if (typeof minItems === "number" && instance.getProperties().length < minItems) {
- report.addError(instance, schema, "minItems", "The number of items is less than the required minimum", minItems);
- }
- }
- }
- },
- "maxItems" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maxItems;
- if (instance.getType() === "array") {
- maxItems = schema.getAttribute("maxItems");
- if (typeof maxItems === "number" && instance.getProperties().length > maxItems) {
- report.addError(instance, schema, "maxItems", "The number of items is greater than the required maximum", maxItems);
- }
- }
- }
- },
- "uniqueItems" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false,
- "parser" : function (instance, self) {
- return !!instance.getValue();
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var value, x, xl, y, yl;
- if (instance.getType() === "array" && schema.getAttribute("uniqueItems")) {
- value = instance.getProperties();
- for (x = 0, xl = value.length - 1; x < xl; ++x) {
- for (y = x + 1, yl = value.length; y < yl; ++y) {
- if (value[x].equals(value[y])) {
- report.addError(instance, schema, "uniqueItems", "Array can only contain unique items", { x : x, y : y });
- }
- }
- }
- }
- }
- },
- "pattern" : {
- "type" : "string",
- "optional" : true,
- "format" : "regex",
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var pattern;
- try {
- pattern = new RegExp(schema.getAttribute("pattern"));
- if (instance.getType() === "string" && pattern && !pattern.test(instance.getValue())) {
- report.addError(instance, schema, "pattern", "String does not match pattern", pattern.toString());
- }
- } catch (e) {
- report.addError(instance, schema, "pattern", "Invalid pattern", e);
- }
- }
- },
- "minLength" : {
- "type" : "integer",
- "optional" : true,
- "minimum" : 0,
- "default" : 0,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- //else
- return 0;
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var minLength;
- if (instance.getType() === "string") {
- minLength = schema.getAttribute("minLength");
- if (typeof minLength === "number" && instance.getValue().length < minLength) {
- report.addError(instance, schema, "minLength", "String is less than the required minimum length", minLength);
- }
- }
- }
- },
- "maxLength" : {
- "type" : "integer",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var maxLength;
- if (instance.getType() === "string") {
- maxLength = schema.getAttribute("maxLength");
- if (typeof maxLength === "number" && instance.getValue().length > maxLength) {
- report.addError(instance, schema, "maxLength", "String is greater than the required maximum length", maxLength);
- }
- }
- }
- },
- "enum" : {
- "type" : "array",
- "optional" : true,
- "minItems" : 1,
- "uniqueItems" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "array") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var enums, x, xl;
- if (instance.getType() !== "undefined") {
- enums = schema.getAttribute("enum");
- if (enums) {
- for (x = 0, xl = enums.length; x < xl; ++x) {
- if (instance.equals(enums[x])) {
- return true;
- }
- }
- report.addError(instance, schema, "enum", "Instance is not one of the possible values", enums);
- }
- }
- }
- },
- "title" : {
- "type" : "string",
- "optional" : true
- },
- "description" : {
- "type" : "string",
- "optional" : true
- },
- "format" : {
- "type" : "string",
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var format, formatValidators;
- if (instance.getType() === "string") {
- format = schema.getAttribute("format");
- formatValidators = self.getValueOfProperty("formatValidators");
- if (typeof format === "string" && formatValidators[format] !== O[format] && typeof formatValidators[format] === "function" && !formatValidators[format].call(this, instance, report)) {
- report.addError(instance, schema, "format", "String is not in the required format", format);
- }
- }
- },
- "formatValidators" : {}
- },
- "contentEncoding" : {
- "type" : "string",
- "optional" : true
- },
- "default" : {
- "type" : "any",
- "optional" : true
- },
- "divisibleBy" : {
- "type" : "number",
- "minimum" : 0,
- "minimumCanEqual" : false,
- "optional" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "number") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var divisor;
- if (instance.getType() === "number") {
- divisor = schema.getAttribute("divisibleBy");
- if (divisor === 0) {
- report.addError(instance, schema, "divisibleBy", "Nothing is divisible by 0", divisor);
- } else if (divisor !== 1 && ((instance.getValue() / divisor) % 1) !== 0) {
- report.addError(instance, schema, "divisibleBy", "Number is not divisible by " + divisor, divisor);
- }
- }
- }
- },
- "disallow" : {
- "type" : ["string", "array"],
- "items" : {"type" : "string"},
- "optional" : true,
- "uniqueItems" : true,
- "parser" : function (instance, self) {
- if (instance.getType() === "string" || instance.getType() === "array") {
- return instance.getValue();
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var disallowedTypes = JSV.toArray(schema.getAttribute("disallow")),
- x, xl, key, typeValidators;
- //for instances that are required to be a certain type
- if (instance.getType() !== "undefined" && disallowedTypes && disallowedTypes.length) {
- typeValidators = self.getValueOfProperty("typeValidators") || {};
- //ensure that type matches for at least one of the required types
- for (x = 0, xl = disallowedTypes.length; x < xl; ++x) {
- key = disallowedTypes[x];
- if (typeValidators[key] !== O[key] && typeof typeValidators[key] === "function") {
- if (typeValidators[key](instance, report)) {
- report.addError(instance, schema, "disallow", "Instance is a disallowed type", disallowedTypes);
- return false;
- }
- }
- /*
- else {
- report.addError(instance, schema, "disallow", "Instance may be a disallowed type", disallowedTypes);
- return false;
- }
- */
- }
- //if we get to this point, type is valid
- return true;
- }
- //else, everything is allowed if no disallowed types are specified
- return true;
- },
- "typeValidators" : TYPE_VALIDATORS
- },
- "extends" : {
- "type" : [{"$ref" : "#"}, "array"],
- "items" : {"$ref" : "#"},
- "optional" : true,
- "default" : {},
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- } else if (instance.getType() === "array") {
- return JSV.mapArray(instance.getProperties(), function (instance) {
- return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
- });
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var extensions = schema.getAttribute("extends"), x, xl;
- if (extensions) {
- if (JSV.isJSONSchema(extensions)) {
- extensions.validate(instance, report, parent, parentSchema, name);
- } else if (JSV.typeOf(extensions) === "array") {
- for (x = 0, xl = extensions.length; x < xl; ++x) {
- extensions[x].validate(instance, report, parent, parentSchema, name);
- }
- }
- }
- }
- }
- },
- "optional" : true,
- "default" : {},
- "fragmentResolution" : "slash-delimited",
- "parser" : function (instance, self) {
- if (instance.getType() === "object") {
- return instance.getEnvironment().createSchema(instance, self);
- }
- },
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var propNames = schema.getPropertyNames(),
- x, xl,
- attributeSchemas = self.getAttribute("properties"),
- validator;
- for (x in attributeSchemas) {
- if (attributeSchemas[x] !== O[x] && attributeSchemas[x].getValueOfProperty("validationRequired")) {
- JSV.pushUnique(propNames, x);
- }
- }
- for (x = 0, xl = propNames.length; x < xl; ++x) {
- if (attributeSchemas[propNames[x]] !== O[propNames[x]]) {
- validator = attributeSchemas[propNames[x]].getValueOfProperty("validator");
- if (typeof validator === "function") {
- validator(instance, schema, attributeSchemas[propNames[x]], report, parent, parentSchema, name);
- }
- }
- }
- },
- "initializer" : function (instance) {
- var link, extension, extended;
- //if there is a link to a different schema, set reference
- link = instance._schema.getLink("describedby", instance);
- if (link && instance._schema._uri !== link) {
- instance.setReference("describedby", link);
- }
- //if instance has a URI link to itself, update it's own URI
- link = instance._schema.getLink("self", instance);
- if (JSV.typeOf(link) === "string") {
- instance._uri = JSV.formatURI(link);
- }
- //if there is a link to the full representation, set reference
- link = instance._schema.getLink("full", instance);
- if (link && instance._uri !== link) {
- instance.setReference("full", link);
- }
- //extend schema
- extension = instance.getAttribute("extends");
- if (JSV.isJSONSchema(extension)) {
- extended = JSV.inherits(extension, instance, true);
- instance = instance._env.createSchema(extended, instance._schema, instance._uri);
- }
- return instance;
- }
- }, true, "http://json-schema.org/schema#");
- HYPERSCHEMA = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA, ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/hyper-schema#",
- "properties" : {
- "links" : {
- "type" : "array",
- "items" : {"$ref" : "links#"},
- "optional" : true,
- "parser" : function (instance, self, arg) {
- var links,
- linkSchemaURI = self.getValueOfProperty("items")["$ref"],
- linkSchema = self.getEnvironment().findSchema(linkSchemaURI),
- linkParser = linkSchema && linkSchema.getValueOfProperty("parser");
- arg = JSV.toArray(arg);
- if (typeof linkParser === "function") {
- links = JSV.mapArray(instance.getProperties(), function (link) {
- return linkParser(link, linkSchema);
- });
- } else {
- links = JSV.toArray(instance.getValue());
- }
- if (arg[0]) {
- links = JSV.filterArray(links, function (link) {
- return link["rel"] === arg[0];
- });
- }
- if (arg[1]) {
- links = JSV.mapArray(links, function (link) {
- var instance = arg[1],
- href = link["href"];
- href = href.replace(/\{(.+)\}/g, function (str, p1, offset, s) {
- var value;
- if (p1 === "-this") {
- value = instance.getValue();
- } else {
- value = instance.getValueOfProperty(p1);
- }
- return value !== undefined ? String(value) : "";
- });
- return href ? JSV.formatURI(instance.resolveURI(href)) : href;
- });
- }
- return links;
- }
- },
- "fragmentResolution" : {
- "type" : "string",
- "optional" : true,
- "default" : "slash-delimited"
- },
- "root" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false
- },
- "readonly" : {
- "type" : "boolean",
- "optional" : true,
- "default" : false
- },
- "pathStart" : {
- "type" : "string",
- "optional" : true,
- "format" : "uri",
- "validator" : function (instance, schema, self, report, parent, parentSchema, name) {
- var pathStart;
- if (instance.getType() !== "undefined") {
- pathStart = schema.getAttribute("pathStart");
- if (typeof pathStart === "string") {
- //TODO: Find out what pathStart is relative to
- if (instance.getURI().indexOf(pathStart) !== 0) {
- report.addError(instance, schema, "pathStart", "Instance's URI does not start with " + pathStart, pathStart);
- }
- }
- }
- }
- },
- "mediaType" : {
- "type" : "string",
- "optional" : true,
- "format" : "media-type"
- },
- "alternate" : {
- "type" : "array",
- "items" : {"$ref" : "#"},
- "optional" : true
- }
- },
- "links" : [
- {
- "href" : "{$ref}",
- "rel" : "full"
- },
- {
- "href" : "{$schema}",
- "rel" : "describedby"
- },
- {
- "href" : "{id}",
- "rel" : "self"
- }
- ]//,
- //not needed as JSV.inherits does the job for us
- //"extends" : {"$ref" : "http://json-schema.org/schema#"}
- }, SCHEMA), true), true, "http://json-schema.org/hyper-schema#");
- ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/hyper-schema#");
- LINKS = ENVIRONMENT.createSchema({
- "$schema" : "http://json-schema.org/hyper-schema#",
- "id" : "http://json-schema.org/links#",
- "type" : "object",
- "properties" : {
- "href" : {
- "type" : "string"
- },
- "rel" : {
- "type" : "string"
- },
- "targetSchema" : {
- "$ref" : "hyper-schema#",
- //need this here because parsers are run before links are resolved
- "parser" : HYPERSCHEMA.getAttribute("parser")
- },
- "method" : {
- "type" : "string",
- "default" : "GET",
- "optional" : true
- },
- "enctype" : {
- "type" : "string",
- "requires" : "method",
- "optional" : true
- },
- "properties" : {
- "type" : "object",
- "additionalProperties" : {"$ref" : "hyper-schema#"},
- "optional" : true,
- "parser" : function (instance, self, arg) {
- var env = instance.getEnvironment(),
- selfEnv = self.getEnvironment(),
- additionalPropertiesSchemaURI = self.getValueOfProperty("additionalProperties")["$ref"];
- if (instance.getType() === "object") {
- if (arg) {
- return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
- } else {
- return JSV.mapObject(instance.getProperties(), function (instance) {
- return env.createSchema(instance, selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
- });
- }
- }
- }
- }
- },
- "parser" : function (instance, self) {
- var selfProperties = self.getProperty("properties");
- if (instance.getType() === "object") {
- return JSV.mapObject(instance.getProperties(), function (property, key) {
- var propertySchema = selfProperties.getProperty(key),
- parser = propertySchema && propertySchema.getValueOfProperty("parser");
- if (typeof parser === "function") {
- return parser(property, propertySchema);
- }
- //else
- return property.getValue();
- });
- }
- return instance.getValue();
- }
- }, HYPERSCHEMA, "http://json-schema.org/links#");
- JSV.registerEnvironment("json-schema-draft-02", ENVIRONMENT);
- if (!JSV.getDefaultEnvironmentID() || JSV.getDefaultEnvironmentID() === "json-schema-draft-01") {
- JSV.setDefaultEnvironmentID("json-schema-draft-02");
- }
- }());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement