You've got a JSON Schema with $ref
pointers to other files and/or URLs. Maybe you know all the referenced files ahead of time. Maybe you don't. Maybe some are local files, and others are remote URLs. Maybe they are a mix of JSON and YAML format. Maybe some of the files contain cross-references to each other.
{
"definitions": {
"person": {
// references an external file
"$ref": "schemas/people/Bruce-Wayne.json"
},
"place": {
// references a sub-schema in an external file
"$ref": "schemas/places.yaml#/definitions/Gotham-City"
},
"thing": {
// references a URL
"$ref": "http://wayne-enterprises.com/things/batmobile"
},
"color": {
// references a value in an external file via an internal reference
"$ref": "#/definitions/thing/properties/colors/black-as-the-night"
}
}
}
JSON Schema $Ref Parser is a full JSON Reference and JSON Pointer implementation that crawls even the most complex JSON Schemas and gives you simple, straightforward JavaScript objects.
- Use JSON or YAML schemas — or even a mix of both!
- Fully supports
$ref
pointers to external files and URLs - Configurable caching of referenced files
- Can bundle multiple files into a single schema that only has internal
$ref
pointers - Can dereference your schema, producing a plain-old JavaScript object that's easy to work with
- Supports circular references, nested references, back-references, and cross-references between files
- Maintains object reference equality &mdash
$ref
pointers to the same value always resolve to the same object instance - Tested in Node, io.js, and all major web browsers on Windows, Mac, and Linux
$RefParser.dereference(mySchema, function(err, schema) {
if (err) {
console.error(err);
}
else {
// `schema` is just a normal JavaScript object that contains your
// entire JSON Schema - even if it spans multiple files
console.log(schema.definitions.person.properties.firstName);
}
});
Or use Promises syntax instead. The following example is the same as above:
$RefParser.dereference(mySchema)
.then(function(schema) {
console.log(schema.definitions.person.properties.firstName);
})
.catch(function(err) {
console.error(err);
});
Install using npm:
npm install json-schema-ref-parser
Then require it in your code:
var $RefParser = require('json-schema-ref-parser');
Install using bower:
bower install json-schema-ref-parser
Then reference ref-parser.js
or ref-parser.min.js
in your HTML:
<script src="bower_components/json-schema-ref-parser/dist/ref-parser.js"></script>
Or, if you're using AMD (Require.js), then import it into your module:
define(["ref-parser"], function($RefParser) { /* your module's code */ })
- Methods
- Objects
- Class methods vs. Instance methods
- Callbacks vs. Promises
-
schema (required) -
string
orobject
A JSON Schema object, or the file path or URL of a JSON Schema file. See theparse
method for more info. -
options (optional) -
object
See options below. -
callback (optional) -
function(err, schema)
A callback that will receive the dereferenced schema object. -
Return Value:
Promise
See Callbacks vs. Promises below.
Dereferences all $ref
pointers in the JSON Schema, replacing each reference with its resolved value. This results in a schema object that does not contain any $ref
pointers. Instead, it's a normal JavaScript object tree that can easily be crawled and used just like any other JavaScript object. This is great for programmatic usage, especially when using tools that don't understand JSON references.
The dereference
method maintains object reference equality, meaning that all $ref
pointers that point to the same object will be replaced with references to the same object. Again, this is great for programmatic usage, but it does introduce the risk of circular references, so be careful if you intend to serialize the schema using JSON.stringify()
. Consider using the bundle
method instead, which does not create circular references.
$RefParser.dereference("my-schema.yaml")
.then(function(schema) {
// The `schema` object is a normal JavaScript object,
// so you can easily access any part of the schema using simple dot notation
console.log(schema.definitions.person.properties.firstName); // => {type: "string"}
// Object reference equality works as expected
schema.definitions.thing === schema.definitions.batmobile; // => true
});
-
schema (required) -
string
orobject
A JSON Schema object, or the file path or URL of a JSON Schema file. See theparse
method for more info. -
options (optional) -
object
See options below. -
callback (optional) -
function(err, schema)
A callback that will receive the bundled schema object. -
Return Value:
Promise
See Callbacks vs. Promises below.
Bundles all referenced files/URLs into a single schema that only has internal $ref
pointers. This lets you split-up your schema however you want while you're building it, but easily combine all those files together when it's time to package or distribute the schema to other people. The resulting schema size will be small, since it will still contain internal JSON references rather than being fully-dereferenced.
This also eliminates the risk of circular references, so the schema can be safely serialized using JSON.stringify()
.
$RefParser.bundle("my-schema.yaml")
.then(function(schema) {
console.log(schema.definitions.person); // => {$ref: "#/definitions/schemas~1people~1Bruce-Wayne.json"}
});
-
schema (required) -
string
orobject
A JSON Schema object, or the file path or URL of a JSON Schema file.
The path can be absolute or relative. In Node, the path is relative toprocess.cwd()
. In the browser, it's relative to the URL of the page. -
options (optional) -
object
See options below. -
callback (optional) -
function(err, schema)
A callback that will receive the parsed schema object, or an error. -
Return Value:
Promise
See Callbacks vs. Promises below.
This method is used internally by other methods, such as
bundle
anddereference
. You probably won't need to call this method yourself.
Parses the given JSON Schema file (in JSON or YAML format), and returns it as a JavaScript object. This method does not resolve $ref
pointers or dereference anything. It simply parses one file and returns it.
$RefParser.parse("my-schema.yaml")
.then(function(schema) {
console.log(schema.definitions.person); // => {$ref: "schemas/people/Bruce-Wayne.json"}
});
-
path (required) -
string
orobject
A JSON Schema object, or the file path or URL of a JSON Schema file. See theparse
method for more info. -
options (optional) -
object
See options below. -
callback (optional) -
function(err, $refs)
A callback that will receive a$Refs
object. -
Return Value:
Promise
See Callbacks vs. Promises below.
This method is used internally by other methods, such as
bundle
anddereference
. You probably won't need to call this method yourself.
Resolves all JSON references ($ref
pointers) in the given JSON Schema file. If it references any other files/URLs, then they will be downloaded and resolved as well (unless options.$refs.external
is false). This method does not dereference anything. It simply gives you a $Refs
object, which is a map of all the resolved references and their values.
$RefParser.resolve("my-schema.yaml")
.then(function($refs) {
// $refs.paths() returns the paths of all the files in your schema
var filePaths = $refs.paths();
// $refs.get() lets you query parts of your schema
var name = $refs.get("schemas/people/Bruce-Wayne.json#/properties/name");
// $refs.set() lets you change parts of your schema
$refs.set("schemas/people/Bruce-Wayne.json#/properties/favoriteColor/default", "black");
});
You can pass an options parameter to any method. You don't need to specify every option - only the ones you want to change.
$RefParser.dereference("my-schema.yaml", {
allow: {
json: false, // Don't allow JSON files
yaml: true // Allow YAML files
},
$refs: {
internal: false // Don't dereference internal $refs, only external
},
cache: {
fs: 1, // Cache local files for 1 second
http: 600 // Cache http URLs for 10 minutes
}
});
Option | Type | Default | Description |
---|---|---|---|
allow.json |
bool | true | Determines whether JSON files are supported |
allow.yaml |
bool | true | Determines whether YAML files are supported (note: all JSON files are also valid YAML files) |
allow.empty |
bool | true | Determines whether it's ok for a $ref pointer to point to an empty file |
allow.unknown |
bool | true | Determines whether it's ok for a $ref pointer to point to an unknown/unsupported file type (such as HTML, text, image, etc.). The default is to resolve unknown files as a Buffer |
$refs.internal |
bool | true | Determines whether internal $ref pointers (such as #/definitions/widget ) will be dereferenced when calling dereference() . Either way, you'll still be able to get the value using $Refs.get() |
$refs.external |
bool | true | Determines whether external $ref pointers get resolved/dereferenced. If false , then no files/URLs will be retrieved. Use this if you only want to allow single-file schemas. |
$refs.circular |
bool | true | Determines whether circular $ref pointers are allowed. If false , then a ReferenceError will be thrown if the schema contains a circular reference. |
cache.fs |
number | 60 | The length of time (in seconds) to cache local files. The default is one minute. Setting to zero will cache forever. |
cache.http |
number | 300 | The length of time (in seconds) to cache HTTP URLs. The default is five minutes. Setting to zero will cache forever. |
cache.https |
number | 300 | The length of time (in seconds) to cache HTTPS URLs. The default is five minutes. Setting to zero will cache forever. |
If you create an instance of the $RefParser
class (rather than just calling the static methods), then the schema
property gives you easy access to the JSON schema. This is the same value that is passed to the callback function (or Promise) when calling the parse
, bundle
, or dereference
methods.
var parser = new $RefParser();
parser.schema; // => null
parser.dereference("my-schema.json")
.then(function(schema) {
typeof parser.schema; // => "object"
schema === parser.schema; // => true
});
When you call the resolve
method, the value that gets passed to the callback function (or Promise) is a $Refs
object. This same object is accessible via the parser.$refs
property of $RefParser
instances.
This object is a map of JSON References and their resolved values. It also has several convenient helper methods that make it easy for you to navigate and manipulate the JSON References.
- Type:
boolean
This property is true
if the schema contains any circular references. You may want to check this property before serializing the dereferenced schema as JSON, since JSON.stringify()
does not support circular references by default.
var parser = new $RefParser();
parser.dereference("my-schema.json")
.then(function() {
if (parser.$refs.circular) {
console.log('The schema contains circular references');
}
});
-
types (optional) -
string
(one or more)
Optionally only return certain types of paths ("fs", "http", "https") -
Return Value:
array
ofstring
Returns the paths/URLs of all the files in your schema (including the main schema file).
$RefParser.resolve("my-schema.json")
.then(function($refs) {
// Get the paths of ALL files in the schema
$refs.paths();
// Get the paths of local files only
$refs.paths("fs");
// Get all URLs
$refs.paths("http", "https");
});
-
types (optional) -
string
(one or more)
Optionally only return values from certain locations ("fs", "http", "https") -
Return Value:
object
Returns a map of paths/URLs and their correspond values.
$RefParser.resolve("my-schema.json")
.then(function($refs) {
// Get ALL paths & values in the schema
// (this is the same as $refs.toJSON())
var values = $refs.values();
values["schemas/people/Bruce-Wayne.json"];
values["schemas/places.yaml"];
values["http://wayne-enterprises.com/things/batmobile"];
});
-
$ref (required) -
string
The JSON Reference path, optionally with a JSON Pointer in the hash -
Return Value:
boolean
Returnstrue
if the given JSON reference has expired (or if it doesn't exist); otherwise, returnsfalse
$RefParser.resolve("my-schema.json")
.then(function($refs) {
// Hasn't expired yet
$refs.isExpired("schemas/places.yaml"); // => false
// Check again after 10 minutes
setTimeout(function() {
$refs.isExpired("schemas/places.yaml"); // => true
}, 600000);
});
- $ref (required) -
string
The JSON Reference path, optionally with a JSON Pointer in the hash
Immediately expires the given JSON reference, so the next time you call a method such as parse
or dereference
, the file will be refreshed rather than reusing the cached value.
$RefParser.resolve("my-schema.json")
.then(function($refs) {
$refs.isExpired("schemas/places.yaml"); // => false
$refs.expire("schemas/places.yaml");
$refs.isExpired("schemas/places.yaml"); // => true
});
-
$ref (required) -
string
The JSON Reference path, optionally with a JSON Pointer in the hash -
Return Value:
boolean
Returnstrue
if the given path exists in the schema; otherwise, returnsfalse
$RefParser.resolve("my-schema.json")
.then(function($refs) {
$refs.exists("schemas/places.yaml#/definitions/Gotham-City"); // => true
$refs.exists("schemas/places.yaml#/definitions/Metropolis"); // => false
});
-
$ref (required) -
string
The JSON Reference path, optionally with a JSON Pointer in the hash -
options (optional) -
object
See options below. -
Return Value:
boolean
Gets the value at the given path in the schema. Throws an error if the path does not exist.
$RefParser.resolve("my-schema.json")
.then(function($refs) {
var value = $refs.get("schemas/people/Bruce-Wayne.json#/properties/address");
});
-
$ref (required) -
string
The JSON Reference path, optionally with a JSON Pointer in the hash -
value (required)
The value to assign. Can be anything (object, string, number, etc.) -
options (optional) -
object
See options below.
Sets the value at the given path in the schema. If the property, or any of its parents, don't exist, they will be created.
$RefParser.resolve("my-schema.json")
.then(function($refs) {
$refs.set("schemas/people/Bruce-Wayne.json#/properties/favoriteColor/default", "black");
});
This object provides simple YAML parsing functions. JSON Schema $Ref Parser uses this object internally for its own YAML parsing, but it is also exposed so you can use it in your code if needed.
-
text (required) -
string
The YAML string to be parsed. -
Return Value:
Returns the parsed value, which can be any valid JSON type (object, array, string, number, etc.)
This method is similar to JSON.parse()
, but it supports YAML in addition to JSON (since any JSON document is also a valid YAML document).
var YAML = $RefParser.YAML;
var text = "title: person \n" +
"required: \n" +
" - name \n" +
" - age \n" +
"properties: \n" +
" name: \n" +
" type: string \n" +
" age: \n" +
" type: number"
var obj = YAML.parse(text);
// {
// title: "person",
// required: ["name", "age"],
// properties: {
// name: {
// type: "string"
// },
// age: {
// type: "number"
// }
// }
// }
-
value (required)
The value to be converted to a YAML string. Can be any valid JSON type (object, array, string, number, etc.) -
Return Value:
string
Returns the a YAML string containing the serialized value
This method is similar to JSON.stringify()
, except that it converts a value to a YAML string instead of a JSON string.
var YAML = $RefParser.YAML;
var obj = {
title: "person",
required: ["name", "age"],
properties: {
name: {
type: "string"
},
age: {
type: "number"
}
}
};
var string = YAML.stringify(obj);
// title: person
// required:
// - name
// - age
// properties:
// name:
// type: string
// age:
// type: number
All of JSON Schema $Ref Parser's methods are available as static (class) methods, and as instance methods. The static methods simply create a new $RefParser
instance and then call the corresponding instance method. Thus, the following line...
$RefParser.resolve("my-schema.json");
... is the same as this:
var parser = new $RefParser();
parser.resolve("my-schema.json");
The difference is that in the second example you now have a reference to parser
, which means you can access the results (parser.schema
and parser.$refs
) anytime you want, rather than just in the callback function. Also, having a $RefParser
instance allows you to benefit from caching, so the next time you call parser.resolve()
, it won't need to re-download those files again (as long as the cache hasn't expired).
Many people prefer ES6 Promise syntax instead of callbacks. JSON Schema $Ref Parser allows you to use whichever one you prefer. Every method accepts an optional callback and returns a Promise. So pick your poison.
JSON Schema files can contain circular $ref pointers, and JSON Schema $Ref Parser fully supports them. Circular references can be resolved and dereferenced just like any other reference. However, if you intend to serialize the dereferenced schema as JSON, then you should be aware that JSON.stringify
does not support circular references by default, so you will need to use a custom replacer function.
You can disable circular references by setting the $refs.circular
option to false
. Then, if a circular reference is found, a ReferenceError
will be thrown.
Another option is to use the bundle
method rather than the dereference
method. Bundling does not result in circular references, because it simply converts external $ref
pointers to internal ones.
"person": {
"properties": {
"name": {
"type": "string"
},
"spouse": {
"type": {
"$ref": "#/person" // circular reference
}
}
}
}
I welcome any contributions, enhancements, and bug-fixes. File an issue on GitHub and submit a pull request.
To build/test the project locally on your computer:
-
Clone this repo
git clone https://github.com/bigstickcarpet/json-schema-ref-parser.git
-
Install dependencies
npm install
-
Run the build script
npm run build
-
Run the unit tests
npm run mocha
(test in Node)
npm run karma
(test in web browsers)
npm test
(test in Node and browsers, and report code coverage)
JSON Schema $Ref Parser is 100% free and open-source, under the MIT license. Use it however you want.