Implemented method `setSchema`

This commit is contained in:
jos 2016-01-12 13:16:13 +01:00
parent a2b84b2dd8
commit 1d9d9c2594
7 changed files with 145 additions and 74 deletions

View File

@ -6,6 +6,8 @@ https://github.com/josdejong/jsoneditor
## not yet released, version 5.1.0
- Implemented support for JSON schema validation, powered by `ajv`.
A JSON schema can be configured via the option `schema` or the method
`setSchema`.
- Added a minimalist bundle to the `dist` folder, excluding `ace` and `ajv`.
- Fixed an error throw when switching to mode "code" via the menu.

View File

@ -20,11 +20,13 @@ Constructs a new JSONEditor.
[Configuration options](#configuration-options).
- `{JSON} json`
Initial JSON data to be loaded into the JSONEditor. Alternatively, the method `JSONEditor.set(json)` can be used to load JSON data into the editor.
*Returns:*
- `{JSONEditor} editor`
New instance of a JSONEditor.
### Configuration options
@ -33,7 +35,7 @@ Constructs a new JSONEditor.
Provide a custom version of the [Ace editor](http://ace.c9.io/) and use this instead of the version that comes embedded with JSONEditor. Only applicable when `mode` is `code`.
- `{function} ajv`
- `{Object} ajv`
Provide a custom instance of [ajv](https://github.com/epoberezkin/ajv), the
library used for JSON schema validation. Example:
@ -124,6 +126,7 @@ Set JSON data.
*Parameters:*
- `{JSON} json`
JSON data to be displayed in the JSONEditor.
#### `JSONEditor.setMode(mode)`
@ -133,6 +136,7 @@ Switch mode. Mode `code` requires the [Ace editor](http://ace.ajax.org/).
*Parameters:*
- `{String} mode`
Available values: `tree`, `view`, `form`, `code`, `text`.
#### `JSONEditor.setName(name)`
@ -142,8 +146,20 @@ Set a field name for the root node.
*Parameters:*
- `{String | undefined} name`
Field name of the root node. If undefined, the current name will be removed.
#### `JSONEditor.setSchema(schema)`
Set a JSON schema for validation of the JSON object. See also option `schema`.
See [http://json-schema.org/](http://json-schema.org/) for more information on the JSON schema definition.
*Parameters:*
- `{Object} schema`
A JSON schema.
#### `JSONEditor.setText(jsonString)`
Set text data in the editor.
@ -154,6 +170,7 @@ valid JSON and the editor is in mode `tree`, `view`, or `form`.
*Parameters:*
- `{String} jsonString`
Contents of the editor as string.
#### `JSONEditor.get()`
@ -166,6 +183,7 @@ which can be the case when the editor is in mode `code` or `text`.
*Returns:*
- `{JSON} json`
JSON data from the JSONEditor.
#### `JSONEditor.getMode()`
@ -175,6 +193,7 @@ Retrieve the current mode of the editor.
*Returns:*
- `{String} mode`
Current mode of the editor for example `tree` or `code`.
#### `JSONEditor.getName()`
@ -184,6 +203,7 @@ Retrieve the current field name of the root node.
*Returns:*
- `{String | undefined} name`
Current field name of the root node, or undefined if not set.
#### `JSONEditor.getText()`
@ -193,6 +213,7 @@ Get JSON data as string.
*Returns:*
- `{String} jsonString`
Contents of the editor as string. When the editor is in code `text` or `code`,
the returned text is returned as-is. For the other modes, the returned text
is a compacted string. In order to get the JSON formatted with a certain

View File

@ -1,3 +1,11 @@
var Ajv;
try {
Ajv = require('ajv/dist/ajv.bundle.js');
}
catch (err) {
// no problem... when we need Ajv we will throw a neat exception
}
var treemode = require('./treemode');
var textmode = require('./textmode');
var util = require('./util');
@ -254,6 +262,51 @@ JSONEditor.prototype._onError = function(err) {
}
};
/**
* Set a JSON schema for validation of the JSON object.
* To remove the schema, call JSONEditor.setSchema(null)
* @param {Object | null} schema
*/
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 });
}
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) {
this.validateSchema = ajv.compile(schema);
// add schema to the options, so that when switching to an other mode,
// the set schema is not lost
this.options.schema = schema;
// validate now
this.validate();
}
}
else {
// remove current schema
this.validateSchema = null;
this.options.schema = null;
this.validate(); // to clear current error messages
}
};
/**
* Validate current JSON object against the configured JSON schema
* Throws an exception when no JSON schema is configured
*/
JSONEditor.prototype.validate = function () {
// must be implemented by treemode and textmode
};
/**
* Register a plugin with one ore multiple modes for the JSON Editor.
*

View File

@ -342,6 +342,14 @@ textmode.setText = function(jsonText) {
}
};
/**
* Validate current JSON object against the configured JSON schema
* Throws an exception when no JSON schema is configured
*/
textmode.validate = function () {
// TODO: implement validate for textmode
};
// define modes
module.exports = [
{

View File

@ -1,10 +1,3 @@
var Ajv;
try {
Ajv = require('ajv/dist/ajv.bundle.js');
}
catch (err) {
// no problem... when we need Ajv we will throw a neat exception
}
var Highlighter = require('./Highlighter');
var History = require('./History');
var SearchBox = require('./SearchBox');
@ -47,6 +40,7 @@ treemode.create = function (container, options) {
this.multiselection = {
nodes: []
};
this.validateSchema = null; // will be set in .setSchema(schema)
this.errorNodes = [];
@ -95,20 +89,7 @@ treemode._setOptions = function (options) {
}
// compile a JSON schema validator if a JSON schema is provided
this._validate = null;
if (this.options.schema) {
var ajv;
try {
// grab ajv from options if provided, else create a new instance
ajv = options.ajv || Ajv({ allErrors: 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) {
this._validate = ajv.compile(this.options.schema);
}
}
this.setSchema(this.options.schema);
// create a debounced validate function
var wait = this.options.debounceInterval;
@ -372,24 +353,30 @@ treemode._onChange = function () {
* Throws an exception when no JSON schema is configured
*/
treemode.validate = function () {
if (!this._validate) {
// clear all current errors
if (this.errorNodes) {
this.errorNodes.forEach(function (node) {
node.setError(null);
});
}
if (!this.validateSchema) {
// if no schema is configured or ajv was not loaded, skip validation
return;
}
var root = this.node;
if (!root) { // TODO: this should be redundant but is needed on mode switch
return;
}
//console.time('validate'); // TODO: clean up time measurement
var valid = this._validate(this.node.getValue());
var valid = this.validateSchema(root.getValue());
//console.timeEnd('validate');
// clear all current errors
this.errorNodes.forEach(function (node) {
node.setError(null);
});
// apply all new errors
var root = this.node;
if (!valid) {
this.errorNodes = this._validate.errors
this.errorNodes = this.validateSchema.errors
.map(function findNode (error) {
return {
node: root.findNode(error.dataPath),

View File

@ -42,7 +42,7 @@
options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
error: function (err) {
onError: function (err) {
alert(err.toString());
}
};

View File

@ -65,7 +65,7 @@
var options = {
mode: 'text',
modes: ['text', 'form', 'tree', 'view'], // allowed modes
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
onError: function (err) {
console.error(err);
},