{"id":13783954,"url":"https://github.com/bugventure/jsen","last_synced_at":"2025-04-05T14:08:43.867Z","repository":{"id":26888522,"uuid":"30349634","full_name":"bugventure/jsen","owner":"bugventure","description":"JSON-Schema validator built for speed","archived":false,"fork":false,"pushed_at":"2017-07-16T22:05:17.000Z","size":1970,"stargazers_count":155,"open_issues_count":7,"forks_count":25,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-26T15:50:56.912Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bugventure.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-05T10:18:59.000Z","updated_at":"2025-03-17T15:15:06.000Z","dependencies_parsed_at":"2022-08-31T00:00:26.064Z","dependency_job_id":null,"html_url":"https://github.com/bugventure/jsen","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugventure%2Fjsen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugventure%2Fjsen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugventure%2Fjsen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugventure%2Fjsen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bugventure","download_url":"https://codeload.github.com/bugventure/jsen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247345854,"owners_count":20924102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T19:00:33.564Z","updated_at":"2025-04-05T14:08:43.840Z","avatar_url":"https://github.com/bugventure.png","language":"JavaScript","funding_links":[],"categories":["Who Uses the Test Suite","JavaScript","JSON Schema Validators"],"sub_categories":["JavaScript"],"readme":"[![JSEN][jsen-img]][jsen-web]\n=================\n\n[![Build][travis-img]][travis-url] [![Coverage][coveralls-img]][coveralls-url] [![Downloads][downloads-img]][npm-url] [![JSEN][jsen-web-badge]][jsen-web]\n\n[![NPM][npm-img]][npm-url]\n\n\u003c!-- [![testling][testling-img]][testling-url] --\u003e\n\njsen (JSON Sentinel) validates your JSON objects using [JSON-Schema](http://json-schema.org/documentation.html).\n\nWebsite: [http://bugventure.github.io/jsen][jsen-web]\n\n### Table of Contents\n\n\u003c!-- MarkdownTOC --\u003e\n\n- [Getting Started](#getting-started)\n- [Performance \u0026 Benchmarks](#performance--benchmarks)\n- [JSON Schema](#json-schema)\n- [Format Validation](#format-validation)\n    - [Custom Formats](#custom-formats)\n- [External Schemas](#external-schemas)\n    - [Remote Schemas](#remote-schemas)\n- [Errors](#errors)\n    - [Custom Errors](#custom-errors)\n    - [Custom Errors for Keywords](#custom-errors-for-keywords)\n    - [Greedy Validation](#greedy-validation)\n- [Gathering Default Values](#gathering-default-values)\n    - [options.copy](#optionscopy)\n    - [options.additionalProperties](#optionsadditionalproperties)\n- [In-Browser Usage](#in-browser-usage)\n- [Tests](#tests)\n- [Contributing](#contributing)\n- [Issues](#issues)\n- [Changelog](#changelog)\n- [License](#license)\n\n\u003c!-- /MarkdownTOC --\u003e\n\n## Getting Started\n\nInstall through NPM in node.\n\n```bash\n$ npm install jsen --save\n```\n\n```javascript\nvar jsen = require('jsen');\nvar validate = jsen({ type: 'string' });\nvar valid = validate('some value');             // true\n```\n\nInstall through Bower in your HTML page.\n\n```bash\n$ bower install jsen\n```\n\n```javascript\n\u003cscript src=\"bower_components/jsen/dist/jsen.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    var validate = jsen({ type: 'string' });    // under window.jsen\n    var valid = validate('some value');         // true\n\u003c/script\u003e\n```\n\nValidation works by passing a JSON schema to build a validator function that can be used to validate a JSON object.\n\nThe validator builder function (`jsen`) throws an error if the first parameter is not a schema object:\n\n```javascript\ntry {\n    // cannot use this string as a schema\n    jsen('not a valid schema');\n}\ncatch (e) {\n    console.log(e);\n}\n```\n\n`jsen` will not throw an error if the provided schema is not compatible with the [JSON-schema version 4 spec](http://json-schema.org/documentation.html). In this case, as per the spec, validation will always succeed for every schema keyword that is incorrectly defined.\n\n```javascript\n\n// this will not throw, but validation will be incorrect\nvar validate = jsen({ type: 'object', properties: ['string', 'number'] });\n\n// validation erroneously passes, because keyword `properties` is ignored\nvar valid = validate({});   // true\n```\n\nIf you need to validate your schema object, you can use a reference to the [JSON meta schema](http://json-schema.org/draft-04/schema). Internally, `jsen` will recognize and validate against the metaschema.\n\n```javascript\nvar validateSchema = jsen({\"$ref\": \"http://json-schema.org/draft-04/schema#\"});\nvar isSchemaValid = validateSchema({ type: 'object' }); // true\n\nisSchemaValid = validateSchema({\n    type: 'object',\n    properties: ['string', 'number']\n});\n// false, because properties is not in correct format\n```\n\n## Performance \u0026 Benchmarks\n\nJSEN uses dynamic code generation to produce a validator function that the V8 engine can optimize for performance. Following is a set of benchmarks where JSEN is compared to other JSON Schema validators for node.\n\n* [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark)\n* [z-schema bencrhmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n* [jsck benchmark](https://github.com/pandastrike/jsck)\n* [themis benchmark](https://github.com/playlyfe/themis)\n* [cosmicrealms.com benchmark](https://github.com/Sembiance/cosmicrealms.com)\n\nMore on V8 optimization: [Performance Tips for JavaScript in V8](http://www.html5rocks.com/en/tutorials/speed/v8/)\n\n## JSON Schema\n\nTo get started with JSON Schema, check out the [JSEN schema guide](http://bugventure.github.io/jsen/json-schema).\n\nFor further reading, check out this [excellent guide to JSON Schema](http://spacetelescope.github.io/understanding-json-schema/UnderstandingJSONSchema.pdf) by Michael Droettboom, et al.\n\nJSEN fully implements draft 4 of the [JSON Schema specification](http://json-schema.org/documentation.html).\n\n## Format Validation\n\nJSEN supports a few built-in formats, as defined by the [JSON Schema spec](http://json-schema.org/latest/json-schema-validation.html#anchor107):\n\n* `date-time`\n* `uri`\n* `email`\n* `ipv4`\n* `ipv6`\n* `hostname`\n\nThese formats are validated against string values only. As per the spec, format validation passes successfully for any non-string value.\n\n```javascript\nvar schema = { format: 'uri' },\n    validate = jsen(schema);\n\nvalidate('invalid/uri');    // false - format validation kicks in for strings\nvalidate({});               // true - does not kick in for non-strings\n```\n\n### Custom Formats\n\nJSEN additionally supports custom format validation. Custom formats are passed in `options.formats` as a second argument to the `jsen` validator builder function.\n\n```javascript\nvar schema = { format: 'uuid' },\n    uuidRegex = '^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$',\n    validate = jsen(schema, {\n        formats: {\n            uuid: uuidRegex\n        }\n    });\n\nvalidate('fad2b4f5-bc3c-44ca-8e17-6d30cf62bdb1');   // true\nvalidate('not-a-valid-UUID');                       // false\n```\n\nA custom format validator can be specified as:\n\n* a regular expression `string`\n* a regular expression `object`\n* a `function (value, schema)` that must return a truthy value if validation passes\n\nUnlike built-in format validators, custom format validators passed in the `options` are run for all data types, not only strings. This allows implementing custom validation behavior for arrays and objects in scenarios, where it is not possible or practical to use only JSON Schema keywords for validation rules.\n\nCustom format validation runs after all built-in keyword validators. This means that an error in any previous keyword validator will stop execution and any custom format validators won't run.\n\n## External Schemas\n\nYou can use references to external schema objects through the `$ref` keyword. You pass external schemas in the `options.schemas` object:\n\n```javascript\nvar external = { type: 'string' },\n    schema = { $ref: '#external' },\n    validate = jsen(schema, {\n        schemas: {\n            external: external\n        }\n    });\n\nvalidate('abc');    // true\nvalidate(123);      // false\n```\n\nIf you expect to have `$ref`s pointing to missing schemas, you can tell JSEN to ignore invalid schema references with the `options.missing$Ref` flag.\n\n```javascript\nvar schema = { $ref: '#missing' },\n    validate;\n\nvalidate = jsen(schema);    // Error: jsen: invalid schema reference #missing\n\nvalidate = jsen(schema, {   // OK, will ignore missing references\n    missing$Ref: true\n})\n```\n\n### Remote Schemas\n\nAlthough JSEN does not automatically fetch remote schemas by making HTTP requests, you can fetch and provide them through the `schemas` option by giving their URIs as object keys.\n\n```javascript\nvar schema = { $ref: 'http://localhost:1234/integer.json' },\n    externalSchema = { type: 'integer' }, // Downloaded from http://localhost:1234/integer.json\n    validate = jsen(schema, {\n        schemas: {\n            'http://localhost:1234/integer.json': externalSchema\n        }\n    });\n```\n\n## Errors\n\nThe validator function (the one called with the object to validate) provides an `errors` array containing all reported errors in a single validation run.\n\n```javascript\nvar validate = jsen({ type: 'string' });\n\nvalidate(123);      // false\nconsole.log(validate.errors)\n// Output: [{ path: '', keyword: 'type' }]\n\n// path - deep (dot-delimited) path to the property that failed validation\n// keyword - the JSON schema keyword that failed validation\n\nvalidate('abc');    // true\n// Output: []\n```\n\nThe `errors` array may contain multiple errors from a single run.\n\n```javascript\nvar validate = jsen({\n    anyOf: [\n        {\n            type: 'object',\n            properties: {\n                tags: { type: 'array' }\n            }\n        },\n        {\n            type: 'object',\n            properties: {\n                comment: { minLength: 1 }\n            }\n        }\n    ]\n});\n\nvalidate({ tags: null, comment: '' });\n\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'tags', keyword: 'type' },\n  { path: 'comment', keyword: 'minLength' },\n  { path: '', keyword: 'anyOf' } ]\n*/\n```\n\nWhen the `additionalProperties` keyword fails validation, the respective error object contains a key by the same name, specifying the property name that was found in the validated object, but was fobidden in the schema:\n\n```javascript\nvar schema = {\n    properties: { foo: {} },\n    additionalProperties: false\n}\n\nvar validate = jsen(schema);\n\nvalidate({ foo: 'foo', bar: 'bar' });   // false\n\nconsole.log(validate.errors);\n/* Output:\n[ { path: '',\n    keyword: 'additionalProperties',\n    additionalProperties: 'bar' } ]\n*/\n```\n\nThe errors array is replaced on every call of the validator function. You can safely modify the array without affecting successive validation runs.\n\n### Custom Errors\n\nYou can define your custom error messages in the schema object through the `invalidMessage` and `requiredMessage` keywords.\n\n```javascript\nvar schema = {\n        type: 'object',\n        properties: {\n            username: {\n                type: 'string',\n                minLength: 5,\n                invalidMessage: 'Invalid username',\n                requiredMessage: 'Username is required'\n            }\n        },\n        required: ['username']\n    };\nvar validate = jsen(schema);\n\nvalidate({});\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'username',\n    keyword: 'required',\n    message: 'Username is required' } ]\n*/\n\nvalidate({ username: '' });\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'username',\n    keyword: 'minLength',\n    message: 'Invalid username' } ]\n*/\n```\n\nCustom 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.\n\n```javascript\nvar schema = {\n        type: 'object',\n        properties: {\n            age: {\n                type: 'integer',\n                minimum: 0,\n                maximum: 100,\n                invalidMessage: 'Invalid age specified'\n            }\n        }\n    };\nvar validate = jsen(schema);\n\nvalidate({ age: 13.3 });\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'age',\n    keyword: 'type',\n    message: 'Invalid age specified' } ]\n*/\n\nvalidate({ age: -5 });\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'age',\n    keyword: 'minimum',\n    message: 'Invalid age specified' } ]\n*/\n\nvalidate({ age: 120 });\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'age',\n    keyword: 'maximum',\n    message: 'Invalid age specified' } ]\n*/\n```\n\nThe `requiredMessage` is assigned to errors coming from the `required` and `dependencies` keywords. For all other validation keywords, the `invalidMessage` is used.\n\n### Custom Errors for Keywords\n\nYou can assign custom error messages to keywords through the `messages` object in the JSON schema.\n\n```javascript\nvar schema = {\n    type: 'object',\n    messages: {\n        type: 'Invalid data type where an object is expected'\n    }\n}\nvar validate = jsen(schema);\n\nvalidate('this is a string, not an object');\nconsole.log(validate.errors);\n/* Output:\n[ { path: '',\n    keyword: 'type',\n    message: 'Invalid data type where an object is expected' } ]\n*/\n```\n\n**NOTE**: The following keywords are never assigned to error objects, and thus do not support custom error messages: `items`, `properties`, `patternProperties`, `dependecies` (when defining a [schema dependency](http://json-schema.org/latest/json-schema-validation.html#anchor70)) and `allOf`.\n\n### Greedy Validation\n\nFor performance, by default, JSEN returns the first encountered error and bails out any further execution.\n\nWith the `options.greedy` flag passed to the builder function, the compiled validator will try to validate as much as possible, providing more info in the `errors` array.\n\n```javascript\nvar schema = {\n        type: 'object',\n        properties: {\n            firstName: {\n                type: 'string',\n                minLength: 1,\n                maxLength: 20\n            },\n            lastName: {\n                type: 'string',\n                minLength: 2,\n                maxLength: 50\n            },\n            age: {\n                type: 'number',\n                minimum: 18,\n                maximum: 100\n            }\n        },\n        required: ['firstName', 'lastName', 'age']\n    };\n\nvar validate = jsen(schema, { greedy: true });  // enable greedy validation\n\nvalidate({ firstName: null, lastName: '' });\n\nconsole.log(validate.errors);\n/* Output:\n[ { path: 'firstName', keyword: 'type' },\n  { path: 'lastName', keyword: 'minLength' },\n  { path: 'age', keyword: 'required' } ]\n*/\n```\n\n## Gathering Default Values\n\nJSEN can collect default values from the schema. The `build(initial, options)` method in the dynamic validator function recursively walks the schema object and compiles the default values into a single object or array.\n\n```javascript\nvar validate = jsen({ type: 'string', default: 'abc' });\nconsole.log(validate.build());      // 'abc'\n\nvar validate = jsen({\n    default: {},\n    properties: {\n        foo: { default: 'bar' },\n        arr: {\n            default: [],\n            items: [\n                { default: 1 },\n                { default: 1 },\n                { default: 2 }\n            ]\n        }\n    }\n});\nconsole.log(validate.build());      // { foo: 'bar', arr: [1, 2, 3] }\n```\n\nThe `build` function can additionally merge the default values with an initially provided data object.\n\n```javascript\nvar validate = jsen({\n    properties: {\n        rememberMe: {\n            default: 'true'\n        }\n    }\n});\n\nvar initial = { username: 'John', password: 'P@$$w0rd' };\n\ninitial = validate.build(initial);\n\nconsole.log(initial);\n// { username: 'John', password: 'P@$$w0rd', rememberMe: true }\n```\n\n### options.copy\n\nBy default, the `build` function creates a copy of the initial data object. You can opt to modify the object in-place by passing `{ copy: false }` as a second argument.\n\n```javascript\nvar initial = { username: 'John', password: 'P@$$w0rd' };\nvar validate = jsen({\n    properties: {\n        rememberMe: {\n            default: 'true'\n        }\n    }\n});\n\nvar withDefaults = validate.build(initial);\nconsole.log(withDefaults === initial);      // false (initial is cloned)\n\nwithDefaults = validate.build(initial, { copy: false });\nconsole.log(withDefaults === initial);      // true (initial is modified)\n```\n\n### options.additionalProperties\n\nThe JSON schema spec allows additional properties by default. In many cases, however, this default behavior may be undesirable, forcing developers to specify `additionalProperties: false` everywhere in their schema objects. JSEN's `build` function can filter out additional properties by specifying `{ additionalProperties: false }` as a second argument.\n\n```javascript\nvar validate = jsen({\n    properties: {\n        foo: {},\n        bar: {}\n    }\n});\n\nvar initial = { foo: 1, bar: 2, baz: 3};\n\ninitial = validate.build(initial, { additionalProperties: false });\n\nconsole.log(initial);   // { foo: 1, bar: 2 }\n```\n\nWhen both `options.additionalProperties` and `schema.additionalProperties` are specified, the latter takes precedence.\n\n```javascript\nvar validate = jsen({\n    additionalProperties: true,\n    properties: {\n        foo: {},\n        bar: {}\n    }\n});\n\nvar initial = { foo: 1, bar: 2, baz: 3};\n\ninitial = validate.build(initial, { additionalProperties: false });\n\nconsole.log(initial);   // { foo: 1, bar: 2, baz: 3 }\n```\n\nNOTE: When `{ additionalProperties: false, copy: false }` is specified in the `build` options, any additional properties will be deleted from the initial data object.\n\nIn some scenarios, you may want to disallow additional properties in the schema, but still keep them when gathering default values with `build()`. This may be required, for example, when you want to explicitly fail validation and display a message to the user, listing any excessive properties that are forbidden by the schema. Setting `{ additionalProperties: 'always' }` will prevent the `build()` function from removing any properties in the initial object.\n\n```javascript\nvar schema = {\n        additionalProperties: false,\n        properties: {\n            foo: {}\n        }\n    };\nvar initial = { foo: 1, bar: 2 };\nvar validate = jsen(schema);\n\nvar withDefaults = validate.build(initial, { additionalProperties: 'always' });\n// withDefaults has both 'foo' and 'bar' keys\n```\n\n## In-Browser Usage\n\nBrowser-compatible builds of `jsen` (with the help of [browserify](http://npmjs.com/package/browserify)) can be found in the `dist` folder. These are built with the [standalone](https://github.com/substack/browserify-handbook#standalone) option of browserify, meaning they will work in node, the browser with globals, and AMD loader environments. In the browser, the `window.jsen` global object will refer to the validator builder function.\n\nLoad from CDN, courtesy of [rawgit](https://rawgit.com/):\n\n```\n//cdn.rawgit.com/bugventure/jsen/v0.6.6/dist/jsen.js\n//cdn.rawgit.com/bugventure/jsen/v0.6.6/dist/jsen.min.js\n```\n\n## Tests\n\nTo run [mocha][mocha] tests in node:\n\n```bash\n[~/github/jsen] $ npm test\n```\n\nTo run the same test suite in the browser, serve the `test/index.html` page in your node web server and navitate to `/test/` path from your browser. The example below uses [node-static](https://www.npmjs.com/package/node-static):\n\n```bash\n[~/github/jsen] $ npm install -g node-static\n...\n[~/github/jsen] $ static .\nserving \".\" at http://127.0.0.1:8080\n# navigate to http://127.0.0.1:8080/test/ in your browser\n```\n\n`jsen` passes all draft 4 test cases specified by the [JSON-Schema-Test-Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) with the exception of zero-terminated float tests.\n\nSource code coverage is provided by [istanbul][istanbul] and visible on [coveralls.io][coveralls-url].\n\n## Contributing\n\nTo contribute to the project, fork the repo, edit and send a Pull Request. Please adhere to the coding guidelines enforced by the [jshint](https://github.com/bugventure/jsen/blob/master/.jshintrc) and [jscs](https://github.com/bugventure/jsen/blob/master/.jscsrc) code checkers.\n\n```bash\n[~/github/jsen] $ jshint lib/ \u0026\u0026 jscs lib/\nNo code style errors found.\n```\n\nAll tests must pass both in node and in the browser.\n\n```bash\n[~/github/jsen] $ npm test\n```\n\nTo build the jsen browser-compatible distribution files, run:\n\n```bash\n[~/github/jsen] $ npm run build\n```\n\nThis will update the files in the `/dist` folder.\n\n## Issues\n\nPlease submit issues to the [jsen issue tracker in GitHub](https://github.com/bugventure/jsen/issues).\n\n## Changelog\n\nRead [changelog.md](changelog.md)\n\n## License\n\n[MIT](LICENSE)\n\n[jsen-web]: http://bugventure.github.io/jsen\n[jsen-img]: http://bugventure.github.io/jsen/assets/images/jsen.png\n[jsen-web-badge]: https://img.shields.io/badge/www-github.io/jsen-40babd.svg\n[travis-url]: https://travis-ci.org/bugventure/jsen\n[travis-img]: https://travis-ci.org/bugventure/jsen.svg?branch=master\n[npm-url]: https://www.npmjs.org/package/jsen\n[npm-img]: https://nodei.co/npm/jsen.png?downloads=true\n[downloads-img]: http://img.shields.io/npm/dm/jsen.svg\n[coveralls-img]: https://img.shields.io/coveralls/bugventure/jsen.svg\n[coveralls-url]: https://coveralls.io/r/bugventure/jsen\n[istanbul]: https://www.npmjs.org/package/istanbul\n[mocha]: http://mochajs.org/\n[testling-img]: https://ci.testling.com/bugventure/jsen.png\n[testling-url]: https://ci.testling.com/bugventure/jsen","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugventure%2Fjsen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbugventure%2Fjsen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugventure%2Fjsen/lists"}