Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
jsen (JSON Sentinel) validates your JSON objects using JSON-Schema.
$ref
$ npm install jsen --save
var jsen = require('jsen');
var validate = jsen({ type: 'string' });
var valid = validate('some value');
Validation works by passing a JSON schema to build a validator function that can be used to validate a JSON object.
The validator builder function (jsen
) throws an error if the first parameter is not a schema object:
try {
// cannot use this string as a schema
jsen('not a valid schema');
}
catch (e) {
console.log(e);
}
jsen
will not throw an error if the provided schema is not compatible with the JSON-schema version 4 spec. In this case, as per the spec, validation will always succeed for every schema keyword that is incorrectly defined.
// this will not throw, but validation will be incorrect
var validate = jsen({ type: 'object', properties: ['string', 'number'] });
// validation erroneously passes, because keyword `properties` is ignored
var valid = validate({}); // true
If you need to validate your schema object, you can use a reference to the JSON meta schema. Internally, jsen
will recognize and validate against the metaschema.
var validateSchema = jsen({"$ref": "http://json-schema.org/draft-04/schema#"});
var isSchemaValid = validateSchema({ type: 'object' }); // true
isSchemaValid = validateSchema({
type: 'object',
properties: ['string', 'number']
});
// false, because properties is not in correct format
jsen
fully implements draft 4 of the JSON Schema specification. Check out this excellent guide to JSON Schema by Michael Droettboom, et al.
A schema is a JavaScript object that specifies the type and structure of another JavaScript object or value. Here are some valid schema objects:
Schema | Matches |
---|---|
{} | any value |
{ type: 'string' } | a JavaScript string |
{ type: 'number' } | a JavaScript number |
{ type: ['string', 'null'] } | either a string or null |
{ type: 'object' } | a JavaScript object |
{ type: 'array', items: { type: 'string' } } | an array containing strings |
string
{
type: 'string', // match a string
minLength: 3, // with minimum length 3 characters
maxLength: 10, // with maximum length 10 character
pattern: '^\\w$' // matching the regex /^\w$/
}
number
{
type: 'number', // match a number
minimum: 0, // with minimum value 0
maximum: 10, // with maximum value 10
exclusiveMinimum: true, // exclude the min value (default: false)
exclusiveMaximum: true, // exclude the max value (default: false)
multipleOf: 2 // the number must be a multiple of 2
}
integer
Same as number
, but matches integers only.
{
type: 'integer', // match an integer number
minimum: 0, // with minimum value 0
maximum: 10, // with maximum value 10
exclusiveMinimum: true, // exclude the min value (default: false)
exclusiveMaximum: true, // exclude the max value (default: false)
multipleOf: 2 // the number must be a multiple of 2
}
boolean
{
type: 'boolean' // match a Boolean value
}
object
{
type: 'object', // match a JavaScript object
minProperties: 2, // having at least 2 properties
maxProperties: 5, // and at most 5 properties
required: ['id', 'name'], // where `id` and `name` are required
properties: { // and the properties are as follows
id: { type: 'string' },
name: { type: 'string' },
price: {
type: 'number',
mininum: 0
},
available: { type: 'boolean' }
},
patternProperties: { // with additional properties, where
'^unit-\w+$': { // the keys match the given regular
type: 'number', // expression and the values are
minimum: 0 // numbers with minimum value of 0
}
},
additionalProperties: false // do not allow any other properties
} // (default: true)
Alternatively additionalProperties
can be an object defining a schema, where each additional property must conform to the specified schema.
{
type: 'object', // match a JavaScript object
additionalProperties: { // with all properties containing
type: 'string' // string values
}
}
You can additionally specify dependencies
in an object schema. There are two types of dependencies:
property dependency
{
type: 'object', // if `price` is defined, then
dependencies: { // these two must also be defined
price: ['unitsInStock', 'quantityPerUnit']
}
}
schema dependency
{
type: 'object',
dependencies: { // if `price` is defined,
price: { // then the object must also
type: 'object', // match the specified schema
properties: {
unitsInStock: {
type: 'integer',
minimum: 0
}
}
}
}
}
array
{
type: 'array', // match a JavaScript array
minItems: 1, // with minimum 1 item
maxItems: 5, // and maximum 5 items
uniqueItems: true, // where items are unique
items: { // and each item is a number
type: 'number'
}
}
Alternatively, you can specify multiple item schemas for positional matching.
{
type: 'array', // match a JavaScript array
items: [ // containing exactly 3 items
{ type: 'string' }, // where first item is a string
{ type: 'number' }, // and second item is a number
{ type: 'boolean' } // and third item is a Boolean value
]
}
null
{
type: 'null' // match a null value
}
any
{
type: 'any' // equivalent to `{}` (matches any value)
}
allOf
{
allOf: [ // match a number conforming to both schemas,
{ // i.e. a numeric value between 3 and 5
type: 'number',
minimum: 0,
maximum: 5
},
{
type: 'number',
minimum: 3,
maximum: 10
}
]
}
anyOf
{
anyOf: [ // match either a string or a number
{ type: 'string' },
{ type: 'number' }
]
}
oneOf
{
oneOf: [ // match exacly one of those schemas,
{ // i.e. a number that is less than 3
type: 'number', // or greater than 5,
maximum: 52 // but not between 3 and 5
},
{
type: 'number',
minimum: 3
}
]
}
not
{
not: { // match a value that is not a JavaScript object
type: 'object'
}
}
$ref
You can refer to types defined in other parts of the schema using the $ref
property. This approach is often combined with the definitions
section in the schema that contains reusable schema definitions.
{
type: 'array', // match an array containing
items: { // items that are positive
$ref: '#/definitions/positiveInteger' // integers
},
definitions: {
positiveInteger: {
type: 'integer',
minimum: 0,
exclusiveMinimum: true
}
}
}
Using references, it becomes possible to validate complex object graphs using recursive schema definitions. For example, the validator itself validates the user schema against the JSON meta-schema.
The validator function (the one called with the object to validate) provides an errors
array containing all reported errors in a single validation run.
var validate = jsen({ type: 'string' });
validate(123); // false
console.log(validate.errors)
// Output: [{ path: '', keyword: 'type' }]
// path - deep (dot-delimited) path to the property that failed validation
// keyword - the JSON schema keyword that failed validation
validate('abc'); // true
// Output: []
The errors
array may contain multiple errors from a single run.
var validate = jsen({
anyOf: [
{
type: 'object',
properties: {
tags: { type: 'array' }
}
},
{
type: 'object',
properties: {
comment: { minLength: 1 }
}
}
]
});
validate({ tags: null, comment: '' });
console.log(validate.errors);
/* Output:
[ { path: 'tags', keyword: 'type' },
{ path: 'comment', keyword: 'minLength' },
{ path: '', keyword: 'anyOf' } ]
*/
The errors array is replaced on every call of the validator function. You can safely modify the array without affecting successive validation runs.
You can define your custom error messages in the schema object through the invalidMessage
and requiredMessage
keywords.
var schema = {
type: 'object',
properties: {
username: {
type: 'string',
minLength: 5,
invalidMessage: 'Invalid username',
requiredMessage: 'Username is required'
}
},
required: ['username']
};
var validate = jsen(schema);
validate({});
console.log(validate.errors);
/* Output:
[ { path: 'username',
keyword: 'required',
message: 'Username is required' } ]
*/
validate({ username: '' });
console.log(validate.errors);
/* Output:
[ { path: 'username',
keyword: 'minLength',
message: 'Invalid username' } ]
*/
Custom error messages are assigned to error objects by path, meaning multiple failed JSON schema keywords on the same path will show the same custom error message.
var schema = {
type: 'object',
properties: {
age: {
type: 'integer',
minimum: 0,
maximum: 100,
invalidMessage: 'Invalid age specified'
}
}
};
var validate = jsen(schema);
validate({ age: 13.3 });
console.log(validate.errors);
/* Output:
[ { path: 'age',
keyword: 'type',
message: 'Invalid age specified' } ]
*/
validate({ age: -5 });
console.log(validate.errors);
/* Output:
[ { path: 'age',
keyword: 'minimum',
message: 'Invalid age specified' } ]
*/
validate({ age: 120 });
console.log(validate.errors);
/* Output:
[ { path: 'age',
keyword: 'maximum',
message: 'Invalid age specified' } ]
*/
The requiredMessage
is assigned to errors coming from the required
and dependencies
keywords. For all other validation keywords, the invalidMessage
is used.
To run mocha tests:
$ npm test
jsen
passes all draft 4 test cases specified by the JSON-Schema-Test-Suite with the exception of:
Source code coverage is provided by istanbul and visible on coveralls.io.
Please submit issues to the jsen issue tracker in GitHub.
required
and dependencies
keywords (#7)multipleOf
doesn't validate data for decimal points (#1)MIT
v0.1.0
required
and dependencies
keywords (#7)FAQs
JSON-Schema validator built for speed
The npm package jsen receives a total of 17,300 weekly downloads. As such, jsen popularity was classified as popular.
We found that jsen demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.