Skip to content

Commit 279c88b

Browse files
committed
Lazy load meta schemas
This defers meta schema initialization until they're actually used. People will probably only use one or two meta schemas so this should save some load time.
1 parent 39f5793 commit 279c88b

File tree

7 files changed

+85
-68
lines changed

7 files changed

+85
-68
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@ JSONSchemer.schema(
117117

118118
# meta schema to use for vocabularies (keyword behavior) and schema validation
119119
# String/JSONSchemer::Schema
120-
# 'https://json-schema.org/draft/2020-12/schema': JSONSchemer::DRAFT202012
121-
# 'https://json-schema.org/draft/2019-09/schema': JSONSchemer::DRAFT201909
122-
# 'http://json-schema.org/draft-07/schema#': JSONSchemer::DRAFT7
123-
# 'http://json-schema.org/draft-06/schema#': JSONSchemer::DRAFT6
124-
# 'http://json-schema.org/draft-04/schema#': JSONSchemer::DRAFT4
125-
# 'http://json-schema.org/schema#': JSONSchemer::DRAFT4
126-
# default: JSONSchemer::DRAFT202012
120+
# 'https://json-schema.org/draft/2020-12/schema': JSONSchemer.draft202012
121+
# 'https://json-schema.org/draft/2019-09/schema': JSONSchemer.draft201909
122+
# 'http://json-schema.org/draft-07/schema#': JSONSchemer.draft7
123+
# 'http://json-schema.org/draft-06/schema#': JSONSchemer.draft6
124+
# 'http://json-schema.org/draft-04/schema#': JSONSchemer.draft4
125+
# 'http://json-schema.org/schema#': JSONSchemer.draft4
126+
# default: JSONSchemer.draft202012
127127
meta_schema: 'https://json-schema.org/draft/2020-12/schema',
128128

129129
# validate `format` (https://json-schema.org/draft/2020-12/json-schema-validation.html#section-7)

lib/json_schemer.rb

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -87,47 +87,6 @@ class InvalidEcmaRegexp < StandardError; end
8787
}
8888
VOCABULARY_ORDER = VOCABULARIES.transform_values.with_index { |_vocabulary, index| index }
8989

90-
DRAFT202012 = Schema.new(
91-
Draft202012::SCHEMA,
92-
:base_uri => Draft202012::BASE_URI,
93-
:ref_resolver => Draft202012::Meta::SCHEMAS.to_proc,
94-
:regexp_resolver => 'ecma'
95-
)
96-
97-
DRAFT201909 = Schema.new(
98-
Draft201909::SCHEMA,
99-
:base_uri => Draft201909::BASE_URI,
100-
:ref_resolver => Draft201909::Meta::SCHEMAS.to_proc,
101-
:regexp_resolver => 'ecma'
102-
)
103-
104-
DRAFT7 = Schema.new(
105-
Draft7::SCHEMA,
106-
:vocabulary => { 'json-schemer://draft7' => true },
107-
:base_uri => Draft7::BASE_URI,
108-
:regexp_resolver => 'ecma'
109-
)
110-
111-
DRAFT6 = Schema.new(
112-
Draft6::SCHEMA,
113-
:vocabulary => { 'json-schemer://draft6' => true },
114-
:base_uri => Draft6::BASE_URI,
115-
:regexp_resolver => 'ecma'
116-
)
117-
118-
DRAFT4 = Schema.new(
119-
Draft4::SCHEMA,
120-
:vocabulary => { 'json-schemer://draft4' => true },
121-
:base_uri => Draft4::BASE_URI,
122-
:regexp_resolver => 'ecma'
123-
)
124-
125-
META_SCHEMAS_BY_BASE_URI_STR = [DRAFT202012, DRAFT201909, DRAFT7, DRAFT6, DRAFT4].each_with_object({}) do |meta_schema, out|
126-
out[meta_schema.base_uri.to_s] = meta_schema
127-
end
128-
META_SCHEMAS_BY_BASE_URI_STR['http://json-schema.org/schema#'] = DRAFT4 # version-less $schema deprecated after Draft 4
129-
META_SCHEMAS_BY_BASE_URI_STR.freeze
130-
13190
WINDOWS_URI_PATH_REGEX = /\A\/[a-z]:/i
13291

13392
FILE_URI_REF_RESOLVER = proc do |uri|
@@ -139,7 +98,7 @@ class InvalidEcmaRegexp < StandardError; end
13998
end
14099

141100
class << self
142-
def schema(schema, meta_schema: DRAFT202012, **options)
101+
def schema(schema, meta_schema: draft202012, **options)
143102
case schema
144103
when String
145104
schema = JSON.parse(schema)
@@ -167,5 +126,65 @@ def valid_schema?(schema, **options)
167126
def validate_schema(schema, **options)
168127
schema(schema, **options).validate_schema
169128
end
129+
130+
def draft202012
131+
@draft202012 ||= Schema.new(
132+
Draft202012::SCHEMA,
133+
:base_uri => Draft202012::BASE_URI,
134+
:ref_resolver => Draft202012::Meta::SCHEMAS.to_proc,
135+
:regexp_resolver => 'ecma'
136+
)
137+
end
138+
139+
def draft201909
140+
@draft201909 ||= Schema.new(
141+
Draft201909::SCHEMA,
142+
:base_uri => Draft201909::BASE_URI,
143+
:ref_resolver => Draft201909::Meta::SCHEMAS.to_proc,
144+
:regexp_resolver => 'ecma'
145+
)
146+
end
147+
148+
def draft7
149+
@draft7 ||= Schema.new(
150+
Draft7::SCHEMA,
151+
:vocabulary => { 'json-schemer://draft7' => true },
152+
:base_uri => Draft7::BASE_URI,
153+
:regexp_resolver => 'ecma'
154+
)
155+
end
156+
157+
def draft6
158+
@draft6 ||= Schema.new(
159+
Draft6::SCHEMA,
160+
:vocabulary => { 'json-schemer://draft6' => true },
161+
:base_uri => Draft6::BASE_URI,
162+
:regexp_resolver => 'ecma'
163+
)
164+
end
165+
166+
def draft4
167+
@draft4 ||= Schema.new(
168+
Draft4::SCHEMA,
169+
:vocabulary => { 'json-schemer://draft4' => true },
170+
:base_uri => Draft4::BASE_URI,
171+
:regexp_resolver => 'ecma'
172+
)
173+
end
174+
end
175+
176+
META_SCHEMA_CALLABLES_BY_BASE_URI_STR = {
177+
Draft202012::BASE_URI.to_s => method(:draft202012),
178+
Draft201909::BASE_URI.to_s => method(:draft201909),
179+
Draft7::BASE_URI.to_s => method(:draft7),
180+
Draft6::BASE_URI.to_s => method(:draft6),
181+
Draft4::BASE_URI.to_s => method(:draft4),
182+
# version-less $schema deprecated after Draft 4
183+
'http://json-schema.org/schema#' => method(:draft4)
184+
}.freeze
185+
186+
META_SCHEMAS_BY_BASE_URI_STR = Hash.new do |hash, base_uri_str|
187+
next unless META_SCHEMA_CALLABLES_BY_BASE_URI_STR.key?(base_uri_str)
188+
hash[base_uri_str] = META_SCHEMA_CALLABLES_BY_BASE_URI_STR.fetch(base_uri_str).call
170189
end
171190
end

lib/json_schemer/draft202012/vocab/core.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ def parse
88
schema.meta_schema = if value == schema.base_uri.to_s
99
schema
1010
else
11-
JSONSchemer::META_SCHEMAS_BY_BASE_URI_STR.fetch(value) do
12-
root.resolve_ref(URI(value))
13-
end
11+
META_SCHEMAS_BY_BASE_URI_STR[value] || root.resolve_ref(URI(value))
1412
end
1513
value
1614
end

test/json_schema_test_suite_test.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ class JSONSchemaTestSuiteTest < Minitest::Test
1616
end
1717

1818
OUTPUT_DRAFTS = {
19-
'draft2020-12' => JSONSchemer::DRAFT202012,
20-
'draft2019-09' => JSONSchemer::DRAFT201909
19+
'draft2020-12' => JSONSchemer.draft202012,
20+
'draft2019-09' => JSONSchemer.draft201909
2121
}
2222
DRAFTS = OUTPUT_DRAFTS.merge(
23-
'draft7' => JSONSchemer::DRAFT7,
24-
'draft6' => JSONSchemer::DRAFT6,
25-
'draft4' => JSONSchemer::DRAFT4
23+
'draft7' => JSONSchemer.draft7,
24+
'draft6' => JSONSchemer.draft6,
25+
'draft4' => JSONSchemer.draft4
2626
)
2727

2828
OUTPUT_SCHEMAS = OUTPUT_DRAFTS.each_with_object({}) do |(draft, _meta_schema), out|
@@ -151,7 +151,7 @@ def test_json_schema_test_suite_output
151151
end
152152

153153
def test_meta_schemas
154-
JSONSchemer::META_SCHEMAS_BY_BASE_URI_STR.each do |_base_uri_str, schemer|
154+
JSONSchemer::META_SCHEMA_CALLABLES_BY_BASE_URI_STR.transform_values(&:call).each_value do |schemer|
155155
assert(schemer.valid_schema?)
156156
assert(JSONSchemer.valid_schema?(schemer.value))
157157
end

test/json_schemer_test.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,11 @@ def test_it_raises_for_unsupported_meta_schema
266266
end
267267

268268
def test_string_meta_schema
269-
assert_equal(JSONSchemer::DRAFT6, JSONSchemer.schema({}, :meta_schema => JSONSchemer::Draft6::BASE_URI.to_s).meta_schema)
269+
assert_equal(JSONSchemer.draft6, JSONSchemer.schema({}, :meta_schema => JSONSchemer::Draft6::BASE_URI.to_s).meta_schema)
270270
end
271271

272272
def test_default_meta_schema
273-
assert_equal(JSONSchemer::DRAFT202012, JSONSchemer::Schema.new({}).meta_schema)
273+
assert_equal(JSONSchemer.draft202012, JSONSchemer::Schema.new({}).meta_schema)
274274
end
275275

276276
def test_draft4_default_id
@@ -306,8 +306,8 @@ def test_it_allows_validating_schemas
306306
'details' => { 'missing_keys' => ['maximum'] }
307307
}
308308

309-
draft7_meta_schema = JSONSchemer::DRAFT7
310-
draft4_meta_schema = JSONSchemer::DRAFT4
309+
draft7_meta_schema = JSONSchemer.draft7
310+
draft4_meta_schema = JSONSchemer.draft4
311311

312312
assert(JSONSchemer.valid_schema?(valid_draft7_schema, :meta_schema => draft7_meta_schema))
313313
refute(JSONSchemer.valid_schema?(invalid_draft7_schema, :meta_schema => draft7_meta_schema))

test/performance/benchmark_json_schema_test_suite.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
gem 'json_schemer', :path => '.'
2020
end
2121

22-
$meta_schema = JSONSchemer::DRAFT4
22+
$meta_schema = JSONSchemer.draft4
2323
$ref_uris = Dir["JSON-Schema-Test-Suite/remotes/**/*.json"].each_with_object({}) do |file, out|
2424
uri = URI("http://localhost:1234#{file.delete_prefix('JSON-Schema-Test-Suite/remotes')}")
2525
out[uri] = JSON.parse(File.read(file))

test/performance/profile.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
end
99

1010
OUTPUT_DRAFTS = {
11-
'draft2020-12' => JSONSchemer::DRAFT202012,
12-
'draft2019-09' => JSONSchemer::DRAFT201909
11+
'draft2020-12' => JSONSchemer.draft202012,
12+
'draft2019-09' => JSONSchemer.draft201909
1313
}
1414
DRAFTS = OUTPUT_DRAFTS.merge(
15-
'draft7' => JSONSchemer::DRAFT7,
16-
'draft6' => JSONSchemer::DRAFT6,
17-
'draft4' => JSONSchemer::DRAFT4
15+
'draft7' => JSONSchemer.draft7,
16+
'draft6' => JSONSchemer.draft6,
17+
'draft4' => JSONSchemer.draft4
1818
)
1919

2020
OUTPUT_SCHEMAS = OUTPUT_DRAFTS.each_with_object({}) do |(draft, _meta_schema), out|

0 commit comments

Comments
 (0)