Giter Club home page Giter Club logo

tv4's Introduction

Tiny Validator (for v4 JSON Schema)

โš ๏ธ This project is no longer actively maintained.

Build Status Dependency Status NPM version

Use json-schema draft v4 to validate simple values and complex objects using a rich validation vocabulary (examples).

There is support for $ref with JSON Pointer fragment paths (other-schema.json#/properties/myKey).

Usage 1: Simple validation

var valid = tv4.validate(data, schema);

If validation returns false, then an explanation of why validation failed can be found in tv4.error.

The error object will look something like:

{
    "code": 0,
    "message": "Invalid type: string",
    "dataPath": "/intKey",
    "schemaPath": "/properties/intKey/type"
}

The "code" property will refer to one of the values in tv4.errorCodes - in this case, tv4.errorCodes.INVALID_TYPE.

To enable external schema to be referenced, you use:

tv4.addSchema(url, schema);

If schemas are referenced ($ref) but not known, then validation will return true and the missing schema(s) will be listed in tv4.missing. For more info see the API documentation below.

Usage 2: Multi-threaded validation

Storing the error and missing schemas does not work well in multi-threaded environments, so there is an alternative syntax:

var result = tv4.validateResult(data, schema);

The result will look something like:

{
    "valid": false,
    "error": {...},
    "missing": [...]
}

Usage 3: Multiple errors

Normally, tv4 stops when it encounters the first validation error. However, you can collect an array of validation errors using:

var result = tv4.validateMultiple(data, schema);

The result will look something like:

{
    "valid": false,
    "errors": [
        {...},
        ...
    ],
    "missing": [...]
}

Asynchronous validation

Support for asynchronous validation (where missing schemas are fetched) can be added by including an extra JavaScript file. Currently, the only version requires jQuery (tv4.async-jquery.js), but the code is very short and should be fairly easy to modify for other libraries (such as MooTools).

Usage:

tv4.validate(data, schema, function (isValid, validationError) { ... });

validationError is simply taken from tv4.error.

Cyclical JavaScript objects

While they don't occur in proper JSON, JavaScript does support self-referencing objects. Any of the above calls support an optional third argument: checkRecursive. If true, tv4 will handle self-referencing objects properly - this slows down validation slightly, but that's better than a hanging script.

Consider this data, notice how both a and b refer to each other:

var a = {};
var b = { a: a };
a.b = b;
var aSchema = { properties: { b: { $ref: 'bSchema' }}};
var bSchema = { properties: { a: { $ref: 'aSchema' }}};
tv4.addSchema('aSchema', aSchema);
tv4.addSchema('bSchema', bSchema);

If the checkRecursive argument were missing, this would throw a "too much recursion" error.

To enable support for this, pass true as additional argument to any of the regular validation methods:

tv4.validate(a, aSchema, true);
tv4.validateResult(data, aSchema, true);
tv4.validateMultiple(data, aSchema, true);

The banUnknownProperties flag

Sometimes, it is desirable to flag all unknown properties as an error. This is especially useful during development, to catch typos and the like, even when extra custom-defined properties are allowed.

As such, tv4 implements "ban unknown properties" mode, enabled by a fourth-argument flag:

tv4.validate(data, schema, checkRecursive, true);
tv4.validateResult(data, schema, checkRecursive, true);
tv4.validateMultiple(data, schema, checkRecursive, true);

API

There are additional api commands available for more complex use-cases:

addSchema(uri, schema)

Pre-register a schema for reference by other schema and synchronous validation.

tv4.addSchema('http://example.com/schema', { ... });
  • uri the uri to identify this schema.
  • schema the schema object.

Schemas that have their id property set can be added directly.

tv4.addSchema({ ... });
getSchema(uri)

Return a schema from the cache.

  • uri the uri of the schema (may contain a # fragment)
var schema = tv4.getSchema('http://example.com/schema');
getSchemaMap()

Return a shallow copy of the schema cache, mapping schema document URIs to schema objects.

var map = tv4.getSchemaMap();

var schema = map[uri];
getSchemaUris(filter)

Return an Array with known schema document URIs.

  • filter optional RegExp to filter URIs
var arr = tv4.getSchemaUris();

// optional filter using a RegExp
var arr = tv4.getSchemaUris(/^https?://example.com/);
getMissingUris(filter)

Return an Array with schema document URIs that are used as $ref in known schemas but which currently have no associated schema data.

Use this in combination with tv4.addSchema(uri, schema) to preload the cache for complete synchronous validation with.

  • filter optional RegExp to filter URIs
var arr = tv4.getMissingUris();

// optional filter using a RegExp
var arr = tv4.getMissingUris(/^https?://example.com/);
dropSchemas()

Drop all known schema document URIs from the cache.

tv4.dropSchemas();
freshApi()

Return a new tv4 instance with no shared state.

var otherTV4 = tv4.freshApi();
reset()

Manually reset validation status from the simple tv4.validate(data, schema). Although tv4 will self reset on each validation there are some implementation scenarios where this is useful.

tv4.reset();
setErrorReporter(reporter)

Sets a custom error reporter. This is a function that accepts three arguments, and returns an error message (string):

tv4.setErrorReporter(function (error, data, schema) {
    return "Error code: " + error.code;
});

The error object already has everything aside from the .message property filled in (so you can use error.params, error.dataPath, error.schemaPath etc.).

If nothing is returned (or the empty string), then it falls back to the default error reporter. To remove a custom error reporter, call tv4.setErrorReporter(null).

language(code)

Sets the language used by the default error reporter.

  • code is a language code, like 'en' or 'en-gb'
tv4.language('en-gb');

If you specify a multi-level language code (e.g. fr-CH), then it will fall back to the generic version (fr) if needed.

addLanguage(code, map)

Add a new template-based language map for the default error reporter (used by tv4.language(code))

  • code is new language code
  • map is an object mapping error IDs or constant names (e.g. 103 or "NUMBER_MAXIMUM") to language strings.
tv4.addLanguage('fr', { ... });

// select for use
tv4.language('fr')

If you register a multi-level language code (e.g. fr-FR), then it will also be registered for plain fr if that does not already exist.

addFormat(format, validationFunction)

Add a custom format validator. (There are no built-in format validators. Several common ones can be found here though)

  • format is a string, corresponding to the "format" value in schemas.
  • validationFunction is a function that either returns:
    • null (meaning no error)
    • an error string (explaining the reason for failure)
tv4.addFormat('decimal-digits', function (data, schema) {
	if (typeof data === 'string' && !/^[0-9]+$/.test(data)) {
		return null;
	}
	return "must be string of decimal digits";
});

Alternatively, multiple formats can be added at the same time using an object:

tv4.addFormat({
	'my-format': function () {...},
	'other-format': function () {...}
});
defineKeyword(keyword, validationFunction)

Add a custom keyword validator.

  • keyword is a string, corresponding to a schema keyword
  • validationFunction is a function that either returns:
    • null (meaning no error)
    • an error string (explaining the reason for failure)
    • an error object (containing some of: code/message/dataPath/schemaPath)
tv4.defineKeyword('my-custom-keyword', function (data, value, schema) {
	if (simpleFailure()) {
		return "Failure";
	} else if (detailedFailure()) {
		return {code: tv4.errorCodes.MY_CUSTOM_CODE, message: {param1: 'a', param2: 'b'}};
	} else {
		return null;
	}
});

schema is the schema upon which the keyword is defined. In the above example, value === schema['my-custom-keyword'].

If an object is returned from the custom validator, and its message is a string, then that is used as the message result. If message is an object, then that is used to populate the (localisable) error template.

defineError(codeName, codeNumber, defaultMessage)

Defines a custom error code.

  • codeName is a string, all-caps underscore separated, e.g. "MY_CUSTOM_ERROR"
  • codeNumber is an integer > 10000, which will be stored in tv4.errorCodes (e.g. tv4.errorCodes.MY_CUSTOM_ERROR)
  • defaultMessage is an error message template to use (assuming translations have not been provided for this code)

An example of defaultMessage might be: "Incorrect moon (expected {expected}, got {actual}"). This is filled out if a custom keyword returns a object message (see above). Translations will be used, if associated with the correct code name/number.

Demos

Basic usage

var schema = {
	"items": {
		"type": "boolean"
	}
};
var data1 = [true, false];
var data2 = [true, 123];

alert("data 1: " + tv4.validate(data1, schema)); // true alert("data 2: " + tv4.validate(data2, schema)); // false alert("data 2 error: " + JSON.stringify(tv4.error, null, 4));

Use of $ref

var schema = {
	"type": "array",
	"items": {"$ref": "#"}
};
var data1 = [[], [[]]];
var data2 = [[], [true, []]];

alert("data 1: " + tv4.validate(data1, schema)); // true alert("data 2: " + tv4.validate(data2, schema)); // false

Missing schema

var schema = {
	"type": "array",
	"items": {"$ref": "http://example.com/schema" }
};
var data = [1, 2, 3];

alert("Valid: " + tv4.validate(data, schema)); // true alert("Missing schemas: " + JSON.stringify(tv4.missing));

Referencing remote schema

tv4.addSchema("http://example.com/schema", {
	"definitions": {
		"arrayItem": {"type": "boolean"}
	}
});
var schema = {
	"type": "array",
	"items": {"$ref": "http://example.com/schema#/definitions/arrayItem" }
};
var data1 = [true, false, true];
var data2 = [1, 2, 3];

alert("data 1: " + tv4.validate(data1, schema)); // true alert("data 2: " + tv4.validate(data2, schema)); // false

Supported platforms

  • Node.js
  • All modern browsers
  • IE >= 7

Installation

You can manually download tv4.js or the minified tv4.min.js and include it in your html to create the global tv4 variable.

Alternately use it as a CommonJS module:

var tv4 = require('tv4');

or as an AMD module (e.g. with requirejs):

require('tv4', function(tv4){
  //use tv4 here
});

There is a command-line tool that wraps this library: tv4-cmd.

npm

$ npm install tv4

bower

$ bower install tv4

component.io

$ component install geraintluff/tv4

Build and test

You can rebuild and run the node and browser tests using node.js and grunt:

Make sure you have the global grunt cli command:

$ npm install grunt-cli -g

Clone the git repos, open a shell in the root folder and install the development dependencies:

$ npm install

Rebuild and run the tests:

$ grunt

It will run a build and display one Spec-style report for the node.js and two Dot-style reports for both the plain and minified browser tests (via phantomJS). You can also use your own browser to manually run the suites by opening test/index.html and test/index-min.html.

Contributing

Pull-requests for fixes and expansions are welcome. Edit the partial files in /source and add your tests in a suitable suite or folder under /test/tests and run grunt to rebuild and run the test suite. Try to maintain an idiomatic coding style and add tests for any new features. It is recommend to discuss big changes in an Issue.

Do you speak another language? tv4 needs internationalisation - please contribute language files to /lang!

Packages using tv4

License

The code is available as "public domain", meaning that it is completely free to use, without any restrictions at all. Read the full license here.

It's also available under an MIT license.

tv4's People

Contributors

albertoleal avatar almavic avatar bartvds avatar boschni avatar ericgj avatar exsilium122 avatar geraintluff avatar ikr avatar imperadeiro98 avatar jasonkarns avatar jgrenat avatar justjico avatar meltuhamy avatar mfilenko avatar nathanrsmith avatar noirbizarre avatar ognian avatar passy avatar paulwib avatar rexso avatar silverbucket avatar sivakumar-kailasam avatar vicary avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tv4's Issues

License request

Hi
Thanks for sharing your cool code. We should would like to adopt your library at my work, but the license is not something our legal team particularly likes (even though I personally think it's especially friendly).

It sure would be easier to adopt your code if you used MIT, Apache-2, BSD, or GPL3 licensing.

Thanks for your consideration.

tv4.async-jquery.js's signatures violates callback-last convention

Noticed this when re-implementing this for node.js.

This slipped with the recent cyclic update:

tv4.validate = function (data, schema, callback, **checkRecursive**) 

The javascript community convention with callbacks is to have them always as final argument, even with variable amount of supported arguments.

Not breaking but should be fixed sometime (like when we figure out how to publish additional schema loaders).

Import test and fixes from forks

It looks like this fork has some interesting test and fixes that might be worth checking out.

Importing the tests should easily show if the errors exist here. Also the defaults, generator and strip modules could be interesting to look into.

Add method to extract external schema urls from used $ref's

Optionally only the ones that aren't loaded yet. This methods could then be used to simplify preloading the schema's for tv4.addSchema() and synchronous validation.

I could have a got at this myself but a complications will be to find a way to resolve nested or recursive references. Do you got an idea on how to approach this?

Required not Behaving as Expected

Here is my JSONSchema

{
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "required": true
        },
        "email": {
            "type": "string",
            "required": true,
            "pattern": "[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
        },
        "level": {
            "type": "string",
            "required": true
        },
        "rank": {
            "type": "integer",
            "required": true
        },
        "number": {
            "type": "integer",
            "required": true
        },
        "experience": {
            "type": "number",
            "required": true
        },
        "next_rank": {
            "type": "number",
            "required": true
        },
        "rank_img": {
            "type": "string",
            "required": true,
            "pattern": "http:"
        }
    },
    "additionalProperties": false,
    "required": true
}

If I do var test = tv.validateMultiple({}, userSchema) and log out test, the result is valid and there are no element in the missing or errors key. If I pass extra keys or use the wrong data type in the validation, I get the expected errors, but required doesn't seem to working. Am I doing something wrong?

Verify npm and bower install

I modified some files in the configs so before we release 1.0.4 I'll need to verify if both work as expected.

Maybe I also look into exporting to component.io (bower's big rival).

Semantic validation with "format" (e.g. "date-time")

Hi Geraint,

I'm new to JSON schema, but as fare as I understand the documentation s.th. like the following should be possible and should result in a not valid instance. Did your schema validator already support semantic validation with "format"?

  it('check format date-time', function () {
    var instance = { "created_at": "-foo-"};
    var schema = {
      "type": "object",
      "properties": {
      "created_at": {
          "format": "date-time",
          "type": "string"
        }
      }
    };
    var result = tv4.validateMultiple(instance, schema);

    expect(result.valid).toBeFalsy()
  });

Thanks a lot, Leif

tv4 npm for nodejs

Hi,
since tv4 is already loadable from node it would be great to be able to use it with npm. All you need is a package,json and that you register at npmjs.org for getting the tv4 name. Writing the package.json and testing it is not time critical, but claiming the name "tv4" at npmjs.org is, since there is already someone who registered "tv4-node"...
Ognian

"additionalProperties: false" not verified in subSchemas

Tested with node.js v 0.10.7 and v 1.0.3 tv4.

It would appear that tv4 isn't validating additionalProperties: false for subSchemas.

var tv4 = require('tv4').tv4;
var assert = require('assert');


var subSchema = {
    "title": "SubSchema",
    "type": "object",
    "properties": {
        "attribute": {"type": "string"}
    },
    "additionalProperties": false
};

var mySchema = {
    "title": "My Schema",
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "subschemas": {"type": "array", "items": "#/definitions/subSchema"}
    },
    "definitions": {
        "subSchema": subSchema
    },
    "additionalProperties": false
};

var validatesOk = {
    "name": "Joe",
    "subschemas": [ {"attribute": "Hello"} ]
};

var addlPropInSubSchema = {
    "name": "Joe",
    "subschemas": [ {"attribute": "Hello", "extra": "Not Allowed"} ]
};

console.log("Testing validateMultiple -- happy path");
var happyPathResult = tv4.validateMultiple(validatesOk, mySchema);
assert(happyPathResult.valid);
assert.equal(happyPathResult.errors.length, 0);

// These should report an error because additionalProperties in subSchema are not allowed.
// Assertions should pass

console.log("***Testing validate -- usage 1");
try {
    var expectedUsage1Result = tv4.validate(addlPropInSubSchema, mySchema);
    assert(!expectedUsage1Result);
} catch(err) {
    console.error(err);
}

console.log("***Testing validateResult -- usage 2");
try {
    var expectedValidateResult = tv4.validate(addlPropInSubSchema, mySchema);
    assert(!expectedValidateResult);
} catch(err) {
    console.error(err);
}


console.log("***Testing validateMultiple -- usage 2");
try {
    var expectedMultipleErrorResult = tv4.validateMultiple(addlPropInSubSchema, mySchema);
    console.dir(expectedMultipleErrorResult);
    assert(!expectedMultipleErrorResult.valid);
    assert.equal(expectedMultipleErrorResult.errors.length, 1);
}  catch(err) {
    console.error(err);
}



Grunt test without PhantomJS?

The PhantomJS testing is very cool, but given that it's not pure JavaScript, we can't guarantee that it will work/build on all systems ever.

It would be nice to have an option for testing/building without it.

Tests from "JSON Schema Test Suite"

They just test pass/fail, not error counts and other stuff we need, but it would be good to plug them in anyway. A standard test suite is a good project, and the more libraries that use it the better.

tv4.async-jquery.js - Bug fixes and cleanup

I noticed that the tv4.async-jquery.js file on the site has a typo (v4 instead of tv4) and really has a few minor typo's that should probably be cleaned up. I know I can make a pull request but the code is so small its just as easy to post it here:

tv4.async-jquery.js

 // Provides support for asynchronous validation (fetching schemas) using jQuery
// Callback is optional third argument to tv4.validate() - if not present, synchronous operation
//     callback(result, error);
if (typeof(tv4.asyncValidate) === 'undefined') {
    tv4.syncValidate = tv4.validate;
    tv4.validate = function (data, schema, callback) {
        if (typeof(callback) === 'undefined') {
            return this.syncValidate(data, schema);
        } else {
            return this.asyncValidate(data, schema, callback);
        }
    };
    tv4.asyncValidate = function (data, schema, callback) {
        var $ = jQuery;
        var result = tv4.validate(data, schema);
        if (!tv4.missing.length) {
            callback(result, tv4.error);
        } else {
      // Make a request for each missing schema
      var missingSchemas = $.map(tv4.missing, function (schemaUri) {
        return $.getJSON(schemaUri).success(function (fetchedSchema) {
          tv4.addSchema(schemaUri, fetchedSchema);
        }).error(function () {
          // If there's an error, just use an empty schema
          tv4.addSchema(schemaUri, {});
        });
      });
      // When all requests done, try again
      $.when.apply($, missingSchemas).done(function () {
        var result = tv4.asyncValidate(data, schema, callback);
      });
    }
  };
}

Changes

  • Changed == undefined to typeof() === 'undefined'
  • Changed tv4.missing.length == 0 to !tv4.missing.length
  • Added in missing ;'s
  • Added an else wrapper around missingSchemas and when.apply block so it doesn't execute no matter what
  • Changed v4.asyncValidate to tv4.asyncValidate

Schema with deeply nested $ref's not resolve more than one deep

Use-case: A "schema" with a ref to a "subSchema", and that "subSchema" has a ref to a "subSubSchema".

When validating the "schema", the validator appears not to test against the "subSubSchema".

I've added two types of schemas: one where the subSubSchema is added as a ref and where the subSubSchema is embedded in the subSchema. The former doesn't appear to work properly, while the latter behaves as expected.

Please see the attached gist:

https://gist.github.com/jmeeks/5706911

I'm not expert with json-schema. Am I missing something?

As an aside, this project is extremely useful.

addSchema with the url provided in schema id

Should this test pass?

var url = "http://example.com/schema" + Math.random();
var schema = {
    "id": url,
    "test" : "value"
};
tv4.addSchema('', schema);
var fetched = tv4.getSchema(url);
return fetched.test == "value";

Missed inline schema (definitions)

The following example:

var doc, schema, tv4;

tv4 = require('./').tv4;

schema = {
  id: 'http://example.com/jsonschema',
  type: 'object',
  properties: {
    test: {
      '$ref': '#/definitions/testDefinitions'
    }
  },
  definitions: {
    testDefinitions: {
      type: 'object',
      properties: {
        prop: {
          type: 'number'
        }
      }
    }
  }
};

doc = {
  test: 1234
};

console.log(tv4.validateResult(doc, schema));

fails with the error:

$ node ref.js 
{ error: null,
  missing: 
   [ 'http://example.com/jsonschema',
     'http://example.com/jsonschema': 'http://example.com/jsonschema' ],
  valid: true }

I did something wrong?

Migrating tests to a known framework?

I really like tv4, so much I used it in the two json-schema validators wrappers I'm in the process of building: one is a grunt plugin and the other a plugin for chai assertion framework.

They should be reliable so I'm setting up testing using mocha, grunt and two runner plugins (one serverside node, the other for browsers in phantomJS).

But I would favour it if any dependants (both human and machine) could be able to run the tv4 tests as well. The php is obviously an obstacle here and the nodetest.js is a bit hackish.

Have you ever considered migrating to a mainstream testing engine? Something that works both for browsers and node, like mocha or jasmine? Would be usable for the users and could allow you add the automated repo testing using travis that all cool pro module have :).

I see this fork by @pykl is moving ahead and has migrated to jasmine and karma (but then went of on it's own path without merging back).

If it's just a legacy or time-investment issue I might be willing to do a setup and migrate your tests to mocha and chai and add a grunt runner, if you'd consider them for merging in this core version.

Plugins using tv4 published

Earlier I mentioned the plugins I was building using tv4, and both are in their first published versions:

Grunt plugin to bulk validate files: grunt-tv4

Chai assertion plugin: chai-json-schema

Next I could send you a pull request with an improved grunt file that also builds the code (hint/concat/minify etc). This way you can run a full build + test automatically, and this will also allow you to use travis-ci (with green build badge and also github pull request validator). It's free and very useful (and cool also :)

Let me know if you'd merge that, and maybe pass me your current buildscript so I can make it identical.

require tv4 issue?

Not sure if the is a bug in the code or documentation. This is using version 1.0.7.

// DOES NOT WORK
var tv4 = require('tv4');
tv4.validate( ... );

// DOES WORK
var tv4 = require('tv4').tv4;
tv4.validate( ... );

Support custom error message

Currently all the error messages are hardcoded.
To support custom error message, e.g. localized, it would be great having an optional parameter defining the messages.

Inconsistent return point

Sorry I don't have a pull request, but my code base has diverged significantly.

The function validateAllOf() does not have a return statement as the last line. Probably should return null; for consistency.

Unable to resolve reference from inside schema definition

This code pass validation without errors or missings

tv4 = require( "tv4" ).tv4

schema = {
  id: "http://some.com"
  some:
    other:
      type: "number"
  data:
    $ref: "#/some/other"
}

tv4.addSchema( schema )
tv4.validate( "42", { $ref: "http://some.com#/data" } )

required oneOf

Hi there,

I'm trying to figure out the best approach to require oneOf a set of properties. I doing positioning and I need to require at least one of "left","right","top" or "bottom".

Maybe I'm missing something, but I can't figure out a good way of doing this. Is perhaps patternProperties the way to go?

Another question - being quite fresh at github - is creating an issues like this an appropriate way of asking these kinds of questions? If not, I apologise.

Regards,
@asbjornenge

Add method to remove registered schemas

I was adding some tests to my chai and grunt plugins and I think tv4 should have a method to drop all currently added schemas.

Do you agree on this? I could implement and add tests for this myself but since this would modify the functional code I would like your advice.

Multithreaded Use?

It appears that the errors (and missing) are maintained in an array global to the tv4 instance.

If I am running tv4 on a server where multiple threads may invoke t4 at the same time, I will have to create multiple instances of tv4 for each thread?

Wouldn't it be better to simple return an object from the call? For example:

    {
        "valid": false, 
        "errors": [ ... ],
        "missing": [ ... ]
    }

Incompatibilities on IE7 & IE8

I'm not sure how many browsers you want to support, but there is code in there which calls Object.keys() and Array.isArray. You may want to include these polyfills for older browsers. The Object.keys poly can probably be shortened significantly since it only has to work against some specific JSON objects.

/**
 * Polyfill for the JS Object.keys function.
 * From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
 */
if ( !Object.keys ) {
    Object.keys = (function () {
        var hasOwnProperty = Object.prototype.hasOwnProperty,
            hasDontEnumBug = !({toString : null}).propertyIsEnumerable( 'toString' ),
            dontEnums = [
                'toString',
                'toLocaleString',
                'valueOf',
                'hasOwnProperty',
                'isPrototypeOf',
                'propertyIsEnumerable',
                'constructor'
            ],
            dontEnumsLength = dontEnums.length;

        return function ( obj ) {
            if ( typeof obj !== 'object' && typeof obj !== 'function' || obj === null ) throw new TypeError( 'Object.keys called on non-object' );

            var result = [];

            for ( var prop in obj ) {
                if ( hasOwnProperty.call( obj, prop ) ) result.push( prop );
            }

            if ( hasDontEnumBug ) {
                for ( var i = 0; i < dontEnumsLength; i++ ) {
                    if ( hasOwnProperty.call( obj, dontEnums[i] ) ) result.push( dontEnums[i] );
                }
            }
            return result;
        }
    })()
}

/**
 * Polyfill for the Array.isArray function
 * todo: Test on IE7 and IE8
 */
Array.isArray || (Array.isArray = function ( a ) {
    return'' + a !== a && {}.toString.call( a ) == '[object Array]'
});

Report list of multiple errors

Right now, tv4 stops at the first validation error. It would be very nice if tv4 would have an option for reporting all validation errors (maybe in an array).

By this way, I can show the user all errors he makes while filling out a form. Otherwise I can only present one error after the other.

oneOf not respected correctly

I am using the oneOf keyword in a schema but my json fails validation. A simplified fragment of my schema is given below. When the document provides option 1 tv4 fails the validation with:

    {[{
      "code":302,
      "message":"Missing required property: option2",
      "dataPath":"/alternatives",
      "schemaPath":"/properties/alternatives/oneOf/1/required/0",
      "subErrors":null
    },
    {
      "code":302,
      "message":"Missing required property: option3",
      "dataPath":"/alternatives",
      "schemaPath":"/properties/alternatives/oneOf/2/required/0",
      "subErrors":null
    }],
    "missing":[],
    "valid":false
  }

I believe that tv4 is wrong in this case because the presence of a correctly formed option1 should satisfy the validator. This is also a difference in behaviour with the Python jsonschema validator.

  "properties": {
    "alternatives": {
      "type": "object",
      "description": "Some options",
      "oneOf": [
        {
          "properties": {
            "option1": {
              "type": "string",
              "pattern": "^pattern for option 1$"
            }
          },
          "additionalProperties": false,
          "required": [
            "option1"
          ]
        },
        {
          "properties": {
            "option2": {
              "type": "string",
              "pattern": "^pattern for option 2$"
            }
          },
          "additionalProperties": false,
          "required": [
            "option2"
          ]
        },
        {
          "properties": {
            "option3": {
              "type": "string",
              "pattern": "^pattern for option 3$"
            }
          },
          "additionalProperties": false,
          "required": [
            "option3"
          ]
        }
      ]
    }
  }

"Better" Format for error reporting

I always wondered why nearly all validators - including tv4 - are presenting errors with a more or less "hardcoded" plain text message.

The problem is now that I still have to make sense of this error message, and construct an appropriate message to the end-user out of this data. If I only have a string I have to parse it first to get a) the actual type of error and b) the object the error refers to.

Imho, it would be much nicer to output an error object instead of a string.

This object should contain:

a) an error code (in form of a number or constant)
b) the actual value where the error occured (as object, not path!)
c) the part of the respective scheme (ditto)

The main difference would be that a developer receives the actual objects, not string values like "/properties/main/type" which have to be parsed first to get to the actual object.

Add some parameter checking on the api

I think the public API could use a bit of parameter checking so it throws some readable errors if values are null/undefined etc.

So this:

Error: tv4.validateMultiple(): 'schema' is not an Object

Instead of:

TypeError: Cannot read property '$ref' of undefined

So the the user knows if they messed up themselves (I did) or hit a bug.

Schema is modified when a property named "id" exists.

I'm not sure if this is valid, but in this scenario, the data validates true when it should be false.

    var schema =  {
        "type": "object",
        "properties": {
            "id": { "type": "integer" }
        },
        "required": ["id"]
    };

    var data1= {id: false};
    var result = tv4.validate(data1, schema);
    console.log(result);

The normSchema() on line 479 needs to check if "id" is an object before calling resolveURL().

Circular javascript structures

While not strictly within scope of validating JSON, I have been using tv4 quite successfully to validate more generic javascript structures and have come across an error.

var a = {};
var b = {};
a.b = b;
b.a = a;
var aSchema = { properties: { b: { $ref: 'bSchema' }}};
var bSchema = { properties: { a: { $ref: 'aSchema' }}};
tv4.addSchema('aSchema', aSchema);
tv4.addSchema('bSchema', bSchema);
tv4.validate(a, aSchema);

This naturally results in a "Too much recursion" error. While such a structure would never occur in JSON, it's possible in the wider world of javascript objects.

http://pastebin.com/JcN1rLZZ This patch is a little bit hacky, but it does work.

Help us to solve issues with validation

When we validate our JSON against JSON Schema its get validated successfully.But in this cases we have noted two issues in your script
1,If we removed a mandatory key/value pair from json no error displayed ( Actually we need to display an error like " Key value pair is missing in json " like some online validators)
2,If we alter the key name no error should be raised.We need to raise some error like invalid JSON

Unexpected exception

Following code throws exception

schema = {
  id: "http://some.com"
  type: { $ref: "/data" }
  data:
    type: "number"
}

tv4.addSchema( schema )
tv4.validate( "42", { $ref: "http://some.com" } )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.