From 6af4143235eae4392c0754ec1964bfe333054288 Mon Sep 17 00:00:00 2001 From: Zachary Carter Date: Mon, 28 May 2012 15:14:09 -0700 Subject: [PATCH] add schema validation --- lib/cli.js | 60 +++++++++++++++++++++++++++++++++++++++------------- package.json | 3 ++- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index ef05083..cf95ba2 100755 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,10 +1,13 @@ #!/usr/bin/env node var fs = require("fs"); +var path = require("path"); var parser = require("./jsonlint").parser; +var JSV = require("JSV").JSV; + var options = require("nomnom") - .scriptName("jsonlint") - .opts({ + .script("jsonlint") + .options({ file: { position: 0, help: "file to parse; otherwise uses stdin" @@ -14,7 +17,7 @@ var options = require("nomnom") string: '-v, --version', help: 'print version and exit', callback: function() { - return JSON.parse(fs.readFileSync(__dirname + "/../package.json", "utf8")).version; + return require("../package").version; } }, sort : { @@ -36,37 +39,64 @@ var options = require("nomnom") flag : true, string: '-c, --compact', help : 'compact error display' + }, + validate : { + string: '-V, --validate', + help : 'a JSON schema to use for validation' + }, + env : { + string: '-e, --environment', + "default": "json-schema-draft-03", + help: 'which specification of JSON Schema the validation file uses' } - }) - .parseArgs(); + }).parse(); if (options.compact) { - var fileName = options.file? options.file + ': ' : ''; - parser.parseError = parser.lexer.parseError = function(str, hash) { - console.error(fileName + 'line '+ hash.loc.first_line +', col '+ hash.loc.last_column +', found: \''+ hash.token +'\' - expected: '+ hash.expected.join(', ') +'.'); - throw new Error(str); - }; + var fileName = options.file? options.file + ': ' : ''; + parser.parseError = parser.lexer.parseError = function(str, hash) { + console.error(fileName + 'line '+ hash.loc.first_line +', col '+ hash.loc.last_column +', found: \''+ hash.token +'\' - expected: '+ hash.expected.join(', ') +'.'); + throw new Error(str); + }; } function parse (source) { try { var parsed = options.sort ? - sortObject(parser.parse(source)) : - parser.parse(source); + sortObject(parser.parse(source)) : + parser.parse(source); + + if (options.validate) { + var env = JSV.createEnvironment(options.env); + var schema = JSON.parse(fs.readFileSync(path.normalize(options.validate), "utf8")); + var report = env.validate(parsed, schema); + if (report.errors.length) { + throw report.errors.reduce(schemaError, 'Validation Errors:'); + } + } + return JSON.stringify(parsed,null,options.indent); } catch (e) { if (! options.compact) { - console.log(e); + console.error(e); } process.exit(1); } } +function schemaError (str, err) { + return str + + "\n\n"+err.message + + "\nuri: " + err.uri + + "\nschemaUri: " + err.schemaUri + + "\nattribute: " + err.attribute + + "\ndetails: " + JSON.stringify(err.details); +} + function main (args) { var source = ''; if (options.file) { - var path = require('path').normalize(options.file); - source = parse(fs.readFileSync(path, "utf8")); + var json = path.normalize(options.file); + source = parse(fs.readFileSync(json, "utf8")); if (options.inplace) { fs.writeSync(fs.openSync(path,'w+'), source, 0, "utf8"); } else { diff --git a/package.json b/package.json index 219214f..003ee4e 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "node": ">= 0.6" }, "dependencies": { - "nomnom": ">= 1.x.x" + "nomnom": ">= 1.5.x", + "JSV": ">= 4.0.x" }, "devDependencies": { "test": "*",