add support for json schema references ($ref)

This commit is contained in:
Meir Rotstein 2017-07-05 00:28:28 +03:00
parent 3a8aa1755c
commit b77deb969c
6 changed files with 102 additions and 17 deletions

View File

@ -102,6 +102,11 @@ Constructs a new JSONEditor.
See [http://json-schema.org/](http://json-schema.org/) for more information. 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` - `{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'. 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. 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)` #### `JSONEditor.setText(jsonString)`
Set text data in the editor. Set text data in the editor.

View File

@ -47,20 +47,41 @@
"description": "Age in years", "description": "Age in years",
"type": "integer", "type": "integer",
"minimum": 0 "minimum": 0
},
"job": {
"$ref": "job"
} }
}, },
"required": ["firstName", "lastName"] "required": ["firstName", "lastName"]
}; };
var job = {
"title": "Job description",
"type": "object",
"properties": {
"company": {
"type": "string"
},
"role": {
"type": "string"
}
}
};
var json = { var json = {
firstName: 'John', firstName: 'John',
lastName: 'Doe', lastName: 'Doe',
gender: null, gender: null,
age: 28 age: 28,
job: {
company: 'freelance',
role: 'developer'
}
}; };
var options = { var options = {
schema: schema schema: schema,
schemaRefs: {"job": job}
}; };
// create the editor // create the editor

View File

@ -79,7 +79,7 @@ function JSONEditor (container, options, json) {
// validate options // validate options
if (options) { if (options) {
var VALID_OPTIONS = [ var VALID_OPTIONS = [
'ajv', 'schema','templates', 'ajv', 'schema', 'schemaRefs','templates',
'ace', 'theme','autocomplete', 'ace', 'theme','autocomplete',
'onChange', 'onEditable', 'onError', 'onModeChange', 'onChange', 'onEditable', 'onError', 'onModeChange',
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' '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 <pre><code>$ref</code></pre>
* @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. * Set a JSON schema for validation of the JSON object.
* To remove the schema, call JSONEditor.setSchema(null) * To remove the schema, call JSONEditor.setSchema(null)
@ -277,15 +311,7 @@ JSONEditor.prototype._onError = function(err) {
JSONEditor.prototype.setSchema = function (schema) { JSONEditor.prototype.setSchema = function (schema) {
// compile a JSON schema validator if a JSON schema is provided // compile a JSON schema validator if a JSON schema is provided
if (schema) { if (schema) {
var ajv; var ajv = this._getAjvInstance();
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`.');
}
if (ajv) { if (ajv) {
this.validateSchema = ajv.compile(schema); this.validateSchema = ajv.compile(schema);

View File

@ -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); this.setSchema(this.options.schema);
}; };

View File

@ -112,6 +112,7 @@ treemode._setOptions = function (options) {
mode: 'tree', mode: 'tree',
name: undefined, // field name of root node name: undefined, // field name of root node
schema: null, schema: null,
schemaRefs: null,
autocomplete: 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 // compile a JSON schema validator if a JSON schema is provided
this.setSchema(this.options.schema); this.setSchema(this.options.schema);

View File

@ -57,22 +57,27 @@
"minimum": 0 "minimum": 0
}, },
"hobbies": { "hobbies": {
"type": "array", "$ref": "hobbies.json"
"items": {
"type": "string"
}
} }
}, },
"required": ["firstName", "lastName"] "required": ["firstName", "lastName"]
}; };
var hobbiesSchema = {
"type": "array",
"items": {
"type": "string"
}
};
var options = { var options = {
mode: 'tree', mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
onError: function (err) { onError: function (err) {
console.error(err); console.error(err);
}, },
schema: schema schema: schema,
schemaRefs: {"hobbies.json": hobbiesSchema}
}; };
var json = { var json = {