diff --git a/README.md b/README.md index f38f92d..433a531 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,9 @@ Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 9+. - JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)). ### Code editor -- Format and compact JSON. - Colorized code (powered by [Ace](https://ace.c9.io)). - Inspect JSON (powered by [Ace](https://ace.c9.io)). +- Format and compact JSON. - JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)). ### Text editor diff --git a/examples/07_json_schema_validation.html b/examples/07_json_schema_validation.html index 720c178..8338b67 100644 --- a/examples/07_json_schema_validation.html +++ b/examples/07_json_schema_validation.html @@ -40,6 +40,9 @@ "lastName": { "type": "string" }, + "gender": { + "enum": ["male", "female"] + }, "age": { "description": "Age in years", "type": "integer", @@ -52,7 +55,8 @@ var json = { firstName: 'John', lastName: 'Doe', - age: 28.5 + gender: null, + age: 28 }; var options = { diff --git a/src/js/treemode.js b/src/js/treemode.js index e2d0986..dc2e28d 100644 --- a/src/js/treemode.js +++ b/src/js/treemode.js @@ -370,12 +370,14 @@ treemode.validate = function () { if (this.validateSchema) { var valid = this.validateSchema(root.getValue()); if (!valid) { + var schema = this.options.schema; + // apply all new errors schemaErrors = this.validateSchema.errors .map(function findNode (error) { return { node: root.findNode(error.dataPath), - error: error + error: improveErrorMessages(error) } }) .filter(function hasNode (entry) { @@ -412,6 +414,29 @@ treemode.validate = function () { }); }; +/** + * Improve the error messages of JSON schema errors + * @param {Object} error + * @return {Object} The error + */ +function improveErrorMessages (error) { + if (error.keyword === 'enum') { + var enums = util.getFromSchema(schema, error.schemaPath); + if (enums) { + enums = enums.map(function (value) { + return JSON.stringify(value); + }); + + if (enums.length > 5) { + enums = enums.slice(0, 5).concat(['(' + (enums.length - 5) + ' more...)']); + } + error.message = 'should be equal to one of: ' + enums.join(', '); + } + } + + return error; +} + /** * Start autoscrolling when given mouse position is above the top of the * editor contents, or below the bottom. diff --git a/src/js/util.js b/src/js/util.js index 747b3cd..738ca26 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -660,6 +660,25 @@ exports.parsePath = function parsePath(jsonPath) { return [prop].concat(parsePath(remainder)) }; +/** + * Retrieve a part of the schema + * @param {Object} schema + * @param {string} schemaPath A path like "#/properties/gender/enum" + * @return {Object} Returns the found part of the schema, or undefined when not found. + */ +exports.getFromSchema = function (schema, schemaPath) { + var path = schemaPath.split('/'); + path.shift(); // remove the first # + + var obj = schema; + var prop; + while (prop = path.shift()) { + obj = obj[prop]; + } + + return obj; +}; + /** * Test whether the child rect fits completely inside the parent rect. * @param {ClientRect} parent