diff --git a/docs/api.md b/docs/api.md index 0c60ea7..4bca237 100644 --- a/docs/api.md +++ b/docs/api.md @@ -102,6 +102,11 @@ Constructs a new JSONEditor. See [http://json-schema.org/](http://json-schema.org/) for more information. +- `{Object} schemaRefs` + + Schemas that are referenced using the `$ref` property from the JSON schema that are set in the `schema` option, + the object structure in the form of `{reference_key: schemaObject}` + - `{boolean} search` Enables a search box in the upper right corner of the JSONEditor. True by default. Only applicable when `mode` is 'tree', 'view', or 'form'. @@ -234,6 +239,20 @@ See [http://json-schema.org/](http://json-schema.org/) for more information on t A JSON schema. +#### `JSONEditor.setSchemaRef(schema, ref)` + +Set a schema that are referenced from the schema that are set on the `schema` option. See also option `schemaRefs`. + +*Parameters:* + +- `{Object} schema` + + A JSON schema. + +- `{String} ref` + + The reference key. + #### `JSONEditor.setText(jsonString)` Set text data in the editor. diff --git a/examples/07_json_schema_validation.html b/examples/07_json_schema_validation.html index 8338b67..e54e3b4 100644 --- a/examples/07_json_schema_validation.html +++ b/examples/07_json_schema_validation.html @@ -47,20 +47,41 @@ "description": "Age in years", "type": "integer", "minimum": 0 + }, + "job": { + "$ref": "job" } }, "required": ["firstName", "lastName"] }; + var job = { + "title": "Job description", + "type": "object", + "properties": { + "company": { + "type": "string" + }, + "role": { + "type": "string" + } + } + }; + var json = { firstName: 'John', lastName: 'Doe', gender: null, - age: 28 + age: 28, + job: { + company: 'freelance', + role: 'developer' + } }; var options = { - schema: schema + schema: schema, + schemaRefs: {"job": job} }; // create the editor diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js index 1cc6788..5b48336 100644 --- a/src/js/JSONEditor.js +++ b/src/js/JSONEditor.js @@ -79,7 +79,7 @@ function JSONEditor (container, options, json) { // validate options if (options) { var VALID_OPTIONS = [ - 'ajv', 'schema','templates', + 'ajv', 'schema', 'schemaRefs','templates', 'ace', 'theme','autocomplete', 'onChange', 'onEditable', 'onError', 'onModeChange', 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' @@ -269,6 +269,40 @@ JSONEditor.prototype._onError = function(err) { } }; +/** + * Returns ajv instance, initiates if not exists + * @returns {Object} ajv + */ +JSONEditor.prototype._getAjvInstance = function () { + if (!this.ajv) { + try { + // grab ajv from options if provided, else create a new instance + this.ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true }); + + } + catch (err) { + console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.'); + } + } + return this.ajv; +}; + +/** + * Set reference schema object for schema which is depended with other schemas using
$ref
+ * @param {Object} schema Schema object
+ * @param {String} ref reference key
+ */
+JSONEditor.prototype.setSchemaRef = function (schema, ref) {
+ if (schema && ref) {
+ var ajv = this._getAjvInstance();
+
+ if (ajv) {
+ ajv.removeSchema(ref);
+ ajv.addSchema(schema, ref);
+ }
+ }
+};
+
/**
* Set a JSON schema for validation of the JSON object.
* To remove the schema, call JSONEditor.setSchema(null)
@@ -277,15 +311,7 @@ JSONEditor.prototype._onError = function(err) {
JSONEditor.prototype.setSchema = function (schema) {
// compile a JSON schema validator if a JSON schema is provided
if (schema) {
- var ajv;
- try {
- // grab ajv from options if provided, else create a new instance
- ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true });
-
- }
- catch (err) {
- console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.');
- }
+ var ajv = this._getAjvInstance();
if (ajv) {
this.validateSchema = ajv.compile(schema);
diff --git a/src/js/textmode.js b/src/js/textmode.js
index 7076fde..3c3fd0d 100644
--- a/src/js/textmode.js
+++ b/src/js/textmode.js
@@ -220,6 +220,12 @@ textmode.create = function (container, options) {
}
}
+ if (this.options.schemaRefs) {
+ for (var ref in this.options.schemaRefs) {
+ this.setSchemaRef(this.options.schemaRefs[ref], ref);
+ }
+ }
+
this.setSchema(this.options.schema);
};
diff --git a/src/js/treemode.js b/src/js/treemode.js
index d3737b4..7aca5b3 100644
--- a/src/js/treemode.js
+++ b/src/js/treemode.js
@@ -112,6 +112,7 @@ treemode._setOptions = function (options) {
mode: 'tree',
name: undefined, // field name of root node
schema: null,
+ schemaRefs: null,
autocomplete: null
};
@@ -124,6 +125,13 @@ treemode._setOptions = function (options) {
}
}
+ // set schema refs before schema compile, is available
+ if (this.options.schemaRefs) {
+ for (var ref in this.options.schemaRefs) {
+ this.setSchemaRef(this.options.schemaRefs[ref], ref);
+ }
+ }
+
// compile a JSON schema validator if a JSON schema is provided
this.setSchema(this.options.schema);
diff --git a/test/test_schema.html b/test/test_schema.html
index 4b60562..56d284f 100644
--- a/test/test_schema.html
+++ b/test/test_schema.html
@@ -57,22 +57,27 @@
"minimum": 0
},
"hobbies": {
- "type": "array",
- "items": {
- "type": "string"
- }
+ "$ref": "hobbies.json"
}
},
"required": ["firstName", "lastName"]
};
+ var hobbiesSchema = {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ };
+
var options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
onError: function (err) {
console.error(err);
},
- schema: schema
+ schema: schema,
+ schemaRefs: {"hobbies.json": hobbiesSchema}
};
var json = {