Skip to content

Commit 7d47967

Browse files
1 parent 28cfb27 commit 7d47967

2 files changed

Lines changed: 44 additions & 13 deletions

File tree

lib/dereference.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ function crawl(obj, path, parents, $refs, options) {
4343
var pointer = $refs._resolve($refPath, options);
4444

4545
// Dereference the JSON reference
46-
obj[key] = value = pointer.value;
46+
value = dereference$Ref(obj, key, pointer.value);
4747

4848
// Crawl the dereferenced value (unless it's circular)
4949
if (parents.indexOf(value) === -1) {
50-
crawl(pointer.value, pointer.path, parents, $refs, options);
50+
crawl(value, pointer.path, parents, $refs, options);
5151
}
5252
}
5353
else if (parents.indexOf(value) === -1) {
@@ -58,3 +58,30 @@ function crawl(obj, path, parents, $refs, options) {
5858
parents.pop();
5959
}
6060
}
61+
62+
/**
63+
* Replaces the specified JSON reference with its resolved value.
64+
*
65+
* @param {object} obj - The object that contains the JSON reference
66+
* @param {string} key - The key of the JSON reference within `obj`
67+
* @param {*} value - The resolved value
68+
* @returns {*} - Returns the new value of the JSON reference
69+
*/
70+
function dereference$Ref(obj, key, value) {
71+
var $refObj = obj[key];
72+
73+
if (value && typeof(value) === 'object' && Object.keys($refObj).length > 1) {
74+
// The JSON reference has additional properties (other than "$ref"),
75+
// so merge the resolved value rather than completely replacing the reference
76+
delete $refObj.$ref;
77+
Object.keys(value).forEach(function(key) {
78+
if (!(key in $refObj)) {
79+
$refObj[key] = value[key];
80+
}
81+
});
82+
}
83+
else {
84+
// Completely replace the original reference with the resolved value
85+
return obj[key] = value;
86+
}
87+
}

lib/pointer.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Pointer.prototype.resolve = function(obj, options) {
5858
for (var i = 0; i < tokens.length; i++) {
5959
if (resolveIf$Ref(this, options)) {
6060
// The $ref path has changed, so append the remaining tokens to the path
61-
this.path += '#/' + tokens.slice(i).join('/');
61+
this.path = util.path.ensureHash(this.path) + '/' + tokens.slice(i).join('/');
6262
}
6363

6464
var token = tokens[i];
@@ -169,16 +169,20 @@ Pointer.parse = function(path) {
169169
function resolveIf$Ref(pointer, options) {
170170
// Is the value a JSON reference? (and allowed?)
171171
if ($Ref.isAllowed$Ref(pointer.value, options)) {
172-
var $refPath = url.resolve(pointer.path, pointer.value.$ref);
173-
174-
// Is the value a reference to itself? If so, then there's nothing to do.
175-
if ($refPath !== pointer.path) {
176-
// Resolve the reference
177-
var resolved = pointer.$ref.$refs._resolve($refPath);
178-
pointer.$ref = resolved.$ref;
179-
pointer.path = resolved.path; // pointer.path = $refPath ???
180-
pointer.value = resolved.value;
181-
return true;
172+
// Does the JSON reference have other properties (other than "$ref")?
173+
// If so, then don't resolve it, since it represents a new type
174+
if (Object.keys(pointer.value).length === 1) {
175+
var $refPath = url.resolve(pointer.path, pointer.value.$ref);
176+
177+
// Is the value a reference to itself? If so, then there's nothing to do.
178+
if ($refPath !== pointer.path) {
179+
// Resolve the reference
180+
var resolved = pointer.$ref.$refs._resolve($refPath);
181+
pointer.$ref = resolved.$ref;
182+
pointer.path = resolved.path; // pointer.path = $refPath ???
183+
pointer.value = resolved.value;
184+
return true;
185+
}
182186
}
183187
}
184188
}

0 commit comments

Comments
 (0)