Skip to content

Commit e73f9fe

Browse files
committed
Use default base URI for exclusive refs
In drafts 7 and earlier, all keywords except `definitions` are ignored when `$ref` is present. This includes `$id`, which means refs are resolved using the schema's inherited base URI (default or parent). Currently, when `$id` is present, the inherited base URI isn't being registered as a ref resolution resource (with `ID_KEYWORD_CLASS.new`), which causes JSON pointer ref resolution to fail. The fix here is to add the exclusive ref case for the `ID_KEYWORD_CLASS.new` call. The rest of the changes are from if/else cleanup. Closes: #146
1 parent 4fafc60 commit e73f9fe

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

lib/json_schemer/schema.rb

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -329,28 +329,27 @@ def parse
329329
VOCABULARY_KEYWORD_CLASS.new(vocabulary, self, '$vocabulary')
330330
end
331331

332-
if root == self && (!value.is_a?(Hash) || !value.key?(meta_schema.id_keyword))
332+
keywords = meta_schema.keywords
333+
exclusive_ref = value.is_a?(Hash) && value.key?('$ref') && keywords.fetch('$ref').exclusive?
334+
335+
if root == self && (!value.is_a?(Hash) || !value.key?(meta_schema.id_keyword) || exclusive_ref)
333336
ID_KEYWORD_CLASS.new(base_uri, self, meta_schema.id_keyword)
334337
end
335338

336-
if value.is_a?(Hash)
337-
keywords = meta_schema.keywords
338-
339-
if value.key?('$ref') && keywords.fetch('$ref').exclusive?
340-
@parsed['$ref'] = keywords.fetch('$ref').new(value.fetch('$ref'), self, '$ref')
341-
defs_keyword = meta_schema.defs_keyword
342-
if value.key?(defs_keyword) && keywords.key?(defs_keyword)
343-
@parsed[defs_keyword] = keywords.fetch(defs_keyword).new(value.fetch(defs_keyword), self, defs_keyword)
344-
end
345-
else
346-
keyword_order = meta_schema.keyword_order
347-
last = keywords.size
348-
349-
value.sort do |(keyword_a, _value_a), (keyword_b, _value_b)|
350-
keyword_order.fetch(keyword_a, last) <=> keyword_order.fetch(keyword_b, last)
351-
end.each do |keyword, value|
352-
@parsed[keyword] ||= keywords.fetch(keyword, UNKNOWN_KEYWORD_CLASS).new(value, self, keyword)
353-
end
339+
if exclusive_ref
340+
@parsed['$ref'] = keywords.fetch('$ref').new(value.fetch('$ref'), self, '$ref')
341+
defs_keyword = meta_schema.defs_keyword
342+
if value.key?(defs_keyword) && keywords.key?(defs_keyword)
343+
@parsed[defs_keyword] = keywords.fetch(defs_keyword).new(value.fetch(defs_keyword), self, defs_keyword)
344+
end
345+
elsif value.is_a?(Hash)
346+
keyword_order = meta_schema.keyword_order
347+
last = keywords.size
348+
349+
value.sort do |(keyword_a, _value_a), (keyword_b, _value_b)|
350+
keyword_order.fetch(keyword_a, last) <=> keyword_order.fetch(keyword_b, last)
351+
end.each do |keyword, value|
352+
@parsed[keyword] ||= keywords.fetch(keyword, UNKNOWN_KEYWORD_CLASS).new(value, self, keyword)
354353
end
355354
end
356355

test/ref_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,20 @@ def test_exclusive_ref_supports_definitions
379379
assert(schema.valid?(1))
380380
refute(schema.valid?('1'))
381381
end
382+
383+
def test_exclusive_ref_supports_definitions_with_id_and_json_pointer
384+
schema = JSONSchemer.schema({
385+
'$schema' => 'http://json-schema.org/draft-07/schema#',
386+
'$id' => 'https://example.com/schema',
387+
'$ref' => '#/definitions/yah',
388+
'definitions' => {
389+
'yah' => {
390+
'$id' => '#yah',
391+
'type' => 'integer'
392+
}
393+
}
394+
})
395+
assert(schema.valid?(1))
396+
refute(schema.valid?('1'))
397+
end
382398
end

0 commit comments

Comments
 (0)