This is not yet another JSON Schema $ref resolver. See key differences and how does it work? to learn more.
yarn add json-ref-escodegen
or if npm is package manager of your choice
npm install json-ref-escodegen --save
- generates JS code instead of object literal supposed to be eventually serialized back to JSON / YAML / any other text format
- highly scalable - it's expected to work on projects rather than single files
- very performant - one of the quickest (if not the quickest) $ref resolver (despite the whole fairly expensive code generation process that takes place - will be even faster when there is plain resolving mode exposed)
- excellent long-term caching possibilities - each $ref is as a separate module (file)
- first-class support for all kinds of circularity
- truly environment agnostic - does not depend on any fs module or browser global
- no concept of resolvers - you are in charge of the whole reading & path parsing process
- no parser included - bring your own!
- no CLI
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import generate, { Dependencies, Traverse } from 'json-ref-escodegen';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const source = path.join(__dirname, 'src/__fixtures__/root.json');
const dist = path.join(__dirname, 'dist/output');
const module = await generate(
source,
{
module: 'esm',
fs: {
read: async (src) => JSON.parse(await fs.promises.readFile(src, 'utf8')),
write: (target, content) => fs.promises.writeFile(path.join(dist, target), content),
},
path,
dependencies: new Dependencies(),
traverse: new Traverse({
skipGetters: false,
}),
transformExternal: (target) => true,
transformInternal: (pointer) => true,
}
);
const { default: dereferenced } = await import(path.join(dist, `${module.id}.mjs`));
console.log(dereferenced);
json-ref-escodegen generates valid JS code for each processed document. Each $ref is a getter pointing at external referenced module, or the same module if it's an internal ref.
index.json
{
"allOf": [
{
"$ref": "./users.json#"
},
{
"$ref": "./user.json#/properties/name"
},
{
"$ref": "./user.json#/properties/age"
}
]
}
user.josn
{
"title": "User",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The user's full name."
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 150
}
}
}
users.json
{
"type": "array",
"items": {
"$ref": "./user.json#"
},
"minItems": 1
}
37043355.mjs
- this is the output forindex.json
import {default as _3899215387} from "./3899215387.mjs";
import {default as _3073295516} from "./3073295516.mjs";
const $ = {
"allOf": Object.defineProperties([{
"$ref": "./users.json#"
}, {
"$ref": "./user.json#/properties/name"
}, {
"$ref": "./user.json#/properties/age"
}], {
0: {
configurable: true,
enumerable: true,
get() {
return _3899215387;
}
},
1: {
configurable: true,
enumerable: true,
get() {
return _3073295516["properties"]["name"];
}
},
2: {
configurable: true,
enumerable: true,
get() {
return _3073295516["properties"]["age"];
}
}
})
};
export {$ as default};
3073295516.mjs
-user.json
const $ = {
"title": "User",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The user's full name."
},
"age": {
"type": "number",
"minimum": 0,
"maximum": 150
}
}
};
export {$ as default};
3899215387.mjs
-users.json
import {default as _3073295516} from "./3073295516.mjs";
const $ = {
"type": "array",
get "items"() {
return _3073295516;
},
"minItems": 1
};
export {$ as default};
It's as simple as importing the generated module and running JSON.stringify
or YAML counterpart.
I strongly recommend usage of YAML due to anchors, or a safe JSON stringifer.