From e6d64ce58a406fb103646abc072cef4414f876b3 Mon Sep 17 00:00:00 2001 From: Ryan Leonard Date: Tue, 21 Mar 2017 16:26:51 -0700 Subject: [PATCH] Added 'resolveLocal()' --- app/lib/json-reference.js | 34 ++++++++++++++++++++++ test/test-json-reference.js | 57 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/app/lib/json-reference.js b/app/lib/json-reference.js index cb97545..912df68 100644 --- a/app/lib/json-reference.js +++ b/app/lib/json-reference.js @@ -1,3 +1,5 @@ +var path = require("path"); + /** * Applies a single JSON reference lookup to an object. Does not resolve references in the returned document. * @param {string} ref the JSON reference to search for - e.g. `"#/foo/bar"` @@ -21,6 +23,38 @@ function jsonSearch(ref, obj) { return current; } +/** + * Resolve all local JSON references in a single document. Resolves absolute references (`#/test/`) and relative paths + * (`../test`), but does not change any references to remote files. + * Mutates the given object with resolved references. + * @param {Object} doc the root JSON document that references are being resolved in. + * @param {Object} obj a section of the JSON document that is being evaluated. + * @param {String} ref the path to the current object inside the JSON document, as a JSON reference. +*/ +function resolveLocal(doc, obj, ref) { + if(typeof obj !== "object") { + throw new TypeError("resolveLocal() must be given an object. Given "+typeof obj); + } + for(var k in obj) { + var val = obj[k]; + if(typeof val !== "object") { continue; } + if(val.$ref) { + var $ref = val.$ref; + if($ref.indexOf("./") === 0 || $ref.indexOf("../") === 0) { + $ref = path.join(ref, k, $ref); + } + if($ref.indexOf("#/") === 0) { + Object.assign(val, jsonSearch($ref, doc)); + delete val.$ref; + } + } + else { + resolveLocal(doc, val, path.join(ref, k)); + } + } +} + module.exports = { jsonSearch: jsonSearch, + resolveLocal: resolveLocal, }; diff --git a/test/test-json-reference.js b/test/test-json-reference.js index 5150c46..2bdc8bd 100644 --- a/test/test-json-reference.js +++ b/test/test-json-reference.js @@ -45,4 +45,61 @@ describe("json-reference.js", function() { }); + describe("resolveLocal()", function() { + + it("should resolve absolute references", function() { + var obj = { + def: {a: 1}, + ref: { "$ref": "#/def" }, + }; + json.resolveLocal(obj, obj, "#/"); + obj.should.deep.equal({ + def: {a: 1}, + ref: {a: 1}, + }); + }); + + it("should resolve relative references", function() { + var obj = { + def: {a: 1}, + ref: { "$ref": "../def" }, + }; + json.resolveLocal(obj, obj, "#/"); + obj.should.deep.equal({ + def: {a: 1}, + ref: {a: 1}, + }); + }); + + it("should resolve deep references", function() { + var obj = { + def: { foo: {a: 1} }, + ref: { + root: { "$ref": "#/def/foo" }, + local: { "$ref": "../../def/foo" }, + }, + }; + json.resolveLocal(obj, obj, "#/"); + obj.should.deep.equal({ + def: { foo: {a: 1} }, + ref: { + root: {a: 1}, + local: {a: 1}, + }, + }); + }); + + it("should leave remote references", function() { + var def = { + relative: { "$ref": "Pet.json" }, + root: { "$ref": "/home/test/Pet.json" }, + remote: { "$ref": "http://example.com/Pet.json" }, + }; + var obj = Object.create(def); + json.resolveLocal(obj, obj, "#/"); + obj.should.deep.equal(def); + }); + + }); + });