json_schema 0.20.4 → 0.20.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/bin/validate-schema +10 -12
- data/lib/json_schema/parser.rb +22 -18
- data/lib/json_schema/reference_expander.rb +12 -0
- data/test/bin_test.rb +5 -6
- data/test/json_schema/reference_expander_test.rb +113 -0
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e21a1e4dc51b894f1374f46872ed71f49d2b45702dc99783286aafefca69f8c8
|
4
|
+
data.tar.gz: 7002f0a54a8de78318b676d9f1c0465dc8ff40d70163b3d83b8fafa412cee52e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9d51a9b64731ad8e2aa3bb79f65e3b7c555a38b181a6a00789b9025903a5049e1be0043a3637456a07d008f8878b2a61f56b3a6b9bacd90c1fc7acb20a5415a
|
7
|
+
data.tar.gz: 71e615dc945f0bd926f41211e56a48424f0f45df706df4394779ebf03d96316764a0b6433b2413469e314d0c1a42d08bcc0f479c2c0b2f3736732c4815993361
|
data/README.md
CHANGED
@@ -67,7 +67,8 @@ ruby -Ilib -Itest test/json_schema/validator_test.rb -n /anyOf/
|
|
67
67
|
|
68
68
|
1. Update the version in `json_schema.gemspec` as appropriate for [semantic
|
69
69
|
versioning](http://semver.org) and add details to `CHANGELOG`.
|
70
|
-
2.
|
70
|
+
2. `git commit` those changes with a message like "Bump version to x.y.z".
|
71
|
+
3. Run the `release` task:
|
71
72
|
|
72
73
|
```
|
73
74
|
bundle exec rake release
|
data/bin/validate-schema
CHANGED
@@ -26,17 +26,15 @@ parser = OptionParser.new { |opts|
|
|
26
26
|
end
|
27
27
|
}
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
success = command.run(ARGV.dup)
|
29
|
+
parser.parse!
|
30
|
+
success = command.run(ARGV.dup)
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
32
|
+
if success
|
33
|
+
command.messages.each { |m| $stdout.puts(m) }
|
34
|
+
elsif !command.errors.empty?
|
35
|
+
command.errors.each { |e| $stderr.puts(e) }
|
36
|
+
exit(1)
|
37
|
+
else
|
38
|
+
print_usage!
|
39
|
+
exit(1)
|
42
40
|
end
|
data/lib/json_schema/parser.rb
CHANGED
@@ -17,6 +17,10 @@ module JsonSchema
|
|
17
17
|
TrueClass => "boolean",
|
18
18
|
}
|
19
19
|
|
20
|
+
# Reuse these frozen objects to avoid allocations
|
21
|
+
EMPTY_ARRAY = [].freeze
|
22
|
+
EMPTY_HASH = {}.freeze
|
23
|
+
|
20
24
|
attr_accessor :errors
|
21
25
|
|
22
26
|
# Basic parsing of a schema. May return a malformed schema! (Use `#parse!`
|
@@ -101,21 +105,21 @@ module JsonSchema
|
|
101
105
|
end
|
102
106
|
|
103
107
|
def parse_all_of(schema)
|
104
|
-
if schema.all_of
|
108
|
+
if schema.all_of && !schema.all_of.empty?
|
105
109
|
schema.all_of = schema.all_of.each_with_index.
|
106
110
|
map { |s, i| parse_data(s, schema, "allOf/#{i}") }
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
110
114
|
def parse_any_of(schema)
|
111
|
-
if schema.any_of
|
115
|
+
if schema.any_of && !schema.any_of.empty?
|
112
116
|
schema.any_of = schema.any_of.each_with_index.
|
113
117
|
map { |s, i| parse_data(s, schema, "anyOf/#{i}") }
|
114
118
|
end
|
115
119
|
end
|
116
120
|
|
117
121
|
def parse_one_of(schema)
|
118
|
-
if schema.one_of
|
122
|
+
if schema.one_of && !schema.one_of.empty?
|
119
123
|
schema.one_of = schema.one_of.each_with_index.
|
120
124
|
map { |s, i| parse_data(s, schema, "oneOf/#{i}") }
|
121
125
|
end
|
@@ -140,7 +144,7 @@ module JsonSchema
|
|
140
144
|
end
|
141
145
|
|
142
146
|
def parse_definitions(schema)
|
143
|
-
if schema.definitions
|
147
|
+
if schema.definitions && !schema.definitions.empty?
|
144
148
|
# leave the original data reference intact
|
145
149
|
schema.definitions = schema.definitions.dup
|
146
150
|
schema.definitions.each do |key, definition|
|
@@ -151,7 +155,7 @@ module JsonSchema
|
|
151
155
|
end
|
152
156
|
|
153
157
|
def parse_dependencies(schema)
|
154
|
-
if schema.dependencies
|
158
|
+
if schema.dependencies && !schema.dependencies.empty?
|
155
159
|
# leave the original data reference intact
|
156
160
|
schema.dependencies = schema.dependencies.dup
|
157
161
|
schema.dependencies.each do |k, s|
|
@@ -181,7 +185,7 @@ module JsonSchema
|
|
181
185
|
end
|
182
186
|
|
183
187
|
def parse_links(schema)
|
184
|
-
if schema.links
|
188
|
+
if schema.links && !schema.links.empty?
|
185
189
|
schema.links = schema.links.each_with_index.map { |l, i|
|
186
190
|
link = Schema::Link.new
|
187
191
|
link.parent = schema
|
@@ -231,7 +235,7 @@ module JsonSchema
|
|
231
235
|
end
|
232
236
|
|
233
237
|
def parse_pattern_properties(schema)
|
234
|
-
if schema.pattern_properties
|
238
|
+
if schema.pattern_properties && !schema.pattern_properties.empty?
|
235
239
|
# leave the original data reference intact
|
236
240
|
properties = schema.pattern_properties.dup
|
237
241
|
properties = properties.map do |k, s|
|
@@ -254,8 +258,8 @@ module JsonSchema
|
|
254
258
|
|
255
259
|
def parse_properties(schema)
|
256
260
|
# leave the original data reference intact
|
257
|
-
schema.properties
|
258
|
-
|
261
|
+
if schema.properties && schema.properties.is_a?(Hash) && !schema.properties.empty?
|
262
|
+
schema.properties = schema.properties.dup
|
259
263
|
schema.properties.each do |key, definition|
|
260
264
|
subschema = parse_data(definition, schema, "properties/#{key}")
|
261
265
|
schema.properties[key] = subschema
|
@@ -282,11 +286,11 @@ module JsonSchema
|
|
282
286
|
schema.default = schema.data["default"]
|
283
287
|
|
284
288
|
# validation: any
|
285
|
-
schema.all_of = validate_type(schema, [Array], "allOf") ||
|
286
|
-
schema.any_of = validate_type(schema, [Array], "anyOf") ||
|
287
|
-
schema.definitions = validate_type(schema, [Hash], "definitions") ||
|
289
|
+
schema.all_of = validate_type(schema, [Array], "allOf") || EMPTY_ARRAY
|
290
|
+
schema.any_of = validate_type(schema, [Array], "anyOf") || EMPTY_ARRAY
|
291
|
+
schema.definitions = validate_type(schema, [Hash], "definitions") || EMPTY_HASH
|
288
292
|
schema.enum = validate_type(schema, [Array], "enum")
|
289
|
-
schema.one_of = validate_type(schema, [Array], "oneOf") ||
|
293
|
+
schema.one_of = validate_type(schema, [Array], "oneOf") || EMPTY_ARRAY
|
290
294
|
schema.not = validate_type(schema, [Hash], "not")
|
291
295
|
schema.type = validate_type(schema, [Array, String], "type")
|
292
296
|
schema.type = [schema.type] if schema.type.is_a?(String)
|
@@ -309,11 +313,11 @@ module JsonSchema
|
|
309
313
|
# validation: object
|
310
314
|
schema.additional_properties =
|
311
315
|
validate_type(schema, BOOLEAN + [Hash], "additionalProperties")
|
312
|
-
schema.dependencies = validate_type(schema, [Hash], "dependencies") ||
|
316
|
+
schema.dependencies = validate_type(schema, [Hash], "dependencies") || EMPTY_HASH
|
313
317
|
schema.max_properties = validate_type(schema, [Integer], "maxProperties")
|
314
318
|
schema.min_properties = validate_type(schema, [Integer], "minProperties")
|
315
|
-
schema.pattern_properties = validate_type(schema, [Hash], "patternProperties") ||
|
316
|
-
schema.properties = validate_type(schema, [Hash], "properties") ||
|
319
|
+
schema.pattern_properties = validate_type(schema, [Hash], "patternProperties") || EMPTY_HASH
|
320
|
+
schema.properties = validate_type(schema, [Hash], "properties") || EMPTY_HASH
|
317
321
|
schema.required = validate_type(schema, [Array], "required")
|
318
322
|
schema.strict_properties = validate_type(schema, BOOLEAN, "strictProperties")
|
319
323
|
|
@@ -358,10 +362,10 @@ module JsonSchema
|
|
358
362
|
end
|
359
363
|
|
360
364
|
def validate_type(schema, types, field)
|
361
|
-
friendly_types =
|
362
|
-
types.map { |t| FRIENDLY_TYPES[t] || t }.sort.uniq.join("/")
|
363
365
|
value = schema.data[field]
|
364
366
|
if !value.nil? && !types.any? { |t| value.is_a?(t) }
|
367
|
+
friendly_types =
|
368
|
+
types.map { |t| FRIENDLY_TYPES[t] || t }.sort.uniq.join("/")
|
365
369
|
message = %{#{value.inspect} is not a valid "#{field}", must be a #{friendly_types}.}
|
366
370
|
@errors << SchemaError.new(schema, message, :invalid_type)
|
367
371
|
nil
|
@@ -93,6 +93,7 @@ module JsonSchema
|
|
93
93
|
if !ref
|
94
94
|
schema_children(ref_schema) do |subschema|
|
95
95
|
next unless subschema.reference
|
96
|
+
next if ref_schema.uri == parent_ref.uri.to_s
|
96
97
|
|
97
98
|
if !subschema.reference.uri && parent_ref
|
98
99
|
subschema.reference = JsonReference::Reference.new("#{parent_ref.uri}#{subschema.reference.pointer}")
|
@@ -146,6 +147,17 @@ module JsonSchema
|
|
146
147
|
end
|
147
148
|
end
|
148
149
|
|
150
|
+
if subschema.items && subschema.items.reference
|
151
|
+
next if subschema.expanded?
|
152
|
+
|
153
|
+
if !subschema.items.reference.uri
|
154
|
+
# The subschema's ref is local to the file that the
|
155
|
+
# subschema is in. Manually reconstruct the reference
|
156
|
+
# so we can resolve it.
|
157
|
+
subschema.items.reference = JsonReference::Reference.new("#{ref.uri}#{subschema.items.reference.pointer}")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
149
161
|
# If we're recursing into a schema via a global reference, then if
|
150
162
|
# the current subschema doesn't have a reference, we have no way of
|
151
163
|
# figuring out what schema we're in. The resolve_pointer method will
|
data/test/bin_test.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
#
|
4
|
-
# The purpose of this sets of tests is just to
|
5
|
-
# where possible so that we can get very basic sanity checks on their syntax
|
6
|
-
# (which is something that of course Ruby can't do by default).
|
4
|
+
# The purpose of this sets of tests is just to test our Ruby executables
|
5
|
+
# where possible so that we can get very basic sanity checks on their syntax.
|
7
6
|
#
|
8
|
-
# We can do this without actually executing them
|
9
|
-
# $0 == __FILE__` statements.
|
7
|
+
# We can do this without actually executing them with a "ruby -c" call.
|
10
8
|
#
|
11
9
|
|
12
10
|
describe "executables in bin/" do
|
@@ -15,6 +13,7 @@ describe "executables in bin/" do
|
|
15
13
|
end
|
16
14
|
|
17
15
|
it "has roughly valid Ruby structure for validate-schema" do
|
18
|
-
|
16
|
+
IO.popen(["ruby", "-c", File.join(@bin_dir, "validate-schema")]) { |io| io.read }
|
17
|
+
assert_equal $?.exitstatus, 0, "Ruby syntax check failed; see error above"
|
19
18
|
end
|
20
19
|
end
|
@@ -265,6 +265,87 @@ describe JsonSchema::ReferenceExpander do
|
|
265
265
|
assert schema.expanded?
|
266
266
|
end
|
267
267
|
|
268
|
+
it "expands a schema with a reference to an external schema in a oneOf array" do
|
269
|
+
sample1 = {
|
270
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
271
|
+
"id" => "http://json-schema.org/draft-04/schema#",
|
272
|
+
"definitions" => {
|
273
|
+
"schemaArray" => {
|
274
|
+
"type" => "array",
|
275
|
+
"minItems" => 1,
|
276
|
+
"items" => { "$ref" => "#" }
|
277
|
+
}
|
278
|
+
}
|
279
|
+
}
|
280
|
+
schema1 = JsonSchema::Parser.new.parse!(sample1)
|
281
|
+
|
282
|
+
sample2 = {
|
283
|
+
"$schema" => "http://json-schema.org/draft-04/hyper-schema#",
|
284
|
+
"id" => "http://json-schema.org/draft-04/hyper-schema#",
|
285
|
+
"allOf" => [
|
286
|
+
{
|
287
|
+
"$ref" => "http://json-schema.org/draft-04/schema#"
|
288
|
+
}
|
289
|
+
]
|
290
|
+
}
|
291
|
+
schema2 = JsonSchema::Parser.new.parse!(sample2)
|
292
|
+
|
293
|
+
store = JsonSchema::DocumentStore.new
|
294
|
+
expander = JsonSchema::ReferenceExpander.new
|
295
|
+
|
296
|
+
store.add_schema(schema1)
|
297
|
+
store.add_schema(schema2)
|
298
|
+
|
299
|
+
expander.expand!(schema2, store: store)
|
300
|
+
|
301
|
+
assert schema1.expanded?
|
302
|
+
assert schema2.expanded?
|
303
|
+
end
|
304
|
+
|
305
|
+
it "expands a schema with a nested reference to an external schema in a oneOf array" do
|
306
|
+
sample1 = {
|
307
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
308
|
+
"id" => "http://json-schema.org/draft-04/schema#",
|
309
|
+
"definitions" => {
|
310
|
+
"thingy" => {
|
311
|
+
"type" => ["string"]
|
312
|
+
},
|
313
|
+
"schemaArray" => {
|
314
|
+
"type" => "array",
|
315
|
+
"minItems" => 1,
|
316
|
+
"items" => { "$ref" => "#/definitions/thingy" }
|
317
|
+
}
|
318
|
+
},
|
319
|
+
"properties" => {
|
320
|
+
"whatsit" => {
|
321
|
+
"$ref" => "#/definitions/schemaArray"
|
322
|
+
},
|
323
|
+
}
|
324
|
+
}
|
325
|
+
schema1 = JsonSchema::Parser.new.parse!(sample1)
|
326
|
+
|
327
|
+
sample2 = {
|
328
|
+
"$schema" => "http://json-schema.org/draft-04/hyper-schema#",
|
329
|
+
"id" => "http://json-schema.org/draft-04/hyper-schema#",
|
330
|
+
"allOf" => [
|
331
|
+
{
|
332
|
+
"$ref" => "http://json-schema.org/draft-04/schema#"
|
333
|
+
}
|
334
|
+
]
|
335
|
+
}
|
336
|
+
schema2 = JsonSchema::Parser.new.parse!(sample2)
|
337
|
+
|
338
|
+
store = JsonSchema::DocumentStore.new
|
339
|
+
expander = JsonSchema::ReferenceExpander.new
|
340
|
+
|
341
|
+
store.add_schema(schema1)
|
342
|
+
store.add_schema(schema2)
|
343
|
+
|
344
|
+
expander.expand!(schema2, store: store)
|
345
|
+
|
346
|
+
assert_equal ["string"], schema2.all_of[0].properties["whatsit"].items.type
|
347
|
+
end
|
348
|
+
|
268
349
|
it "expands a schema with a reference to an external schema with a nested external property reference" do
|
269
350
|
sample1 = {
|
270
351
|
"$schema" => "http://json-schema.org/draft-04/hyper-schema",
|
@@ -373,6 +454,38 @@ describe JsonSchema::ReferenceExpander do
|
|
373
454
|
assert_equal 3, schema1.properties["foo"].properties["bar"].one_of[1].properties["baz"].max_length
|
374
455
|
end
|
375
456
|
|
457
|
+
it "does not infinitely recurse when external ref is local to its schema" do
|
458
|
+
sample1 = {
|
459
|
+
"id" => "http://json-schema.org/draft-04/schema#",
|
460
|
+
"$schema" => "http://json-schema.org/draft-04/schema#",
|
461
|
+
"properties" => {
|
462
|
+
"additionalItems" => {
|
463
|
+
"anyOf" => [ { "$ref" => "#" } ]
|
464
|
+
}
|
465
|
+
}
|
466
|
+
}
|
467
|
+
schema1 = JsonSchema::Parser.new.parse!(sample1)
|
468
|
+
sample2 = {
|
469
|
+
"$schema" => "http://json-schema.org/draft-04/hyper-schema#",
|
470
|
+
"id" => "http://json-schema.org/draft-04/hyper-schema#",
|
471
|
+
"allOf" => [
|
472
|
+
{ "$ref" => "http://json-schema.org/draft-04/schema#" }
|
473
|
+
]
|
474
|
+
}
|
475
|
+
schema2 = JsonSchema::Parser.new.parse!(sample2)
|
476
|
+
|
477
|
+
store = JsonSchema::DocumentStore.new
|
478
|
+
expander = JsonSchema::ReferenceExpander.new
|
479
|
+
|
480
|
+
store.add_schema(schema1)
|
481
|
+
store.add_schema(schema2)
|
482
|
+
|
483
|
+
expander.expand!(schema2, store: store)
|
484
|
+
|
485
|
+
assert schema1.expanded?
|
486
|
+
assert schema2.expanded?
|
487
|
+
end
|
488
|
+
|
376
489
|
it "it handles oneOf with nested references to a local schema" do
|
377
490
|
sample1 = {
|
378
491
|
"$schema" => "http://json-schema.org/draft-04/hyper-schema",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.20.
|
4
|
+
version: 0.20.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -69,8 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
|
-
|
73
|
-
rubygems_version: 2.7.3
|
72
|
+
rubygems_version: 3.1.4
|
74
73
|
signing_key:
|
75
74
|
specification_version: 4
|
76
75
|
summary: A JSON Schema V4 and Hyperschema V4 parser and validator.
|