json_schema 0.20.3 → 0.20.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45216e42386e80c6e481d45fafb3bcecad1c55cde5137efb455bb45261e87424
4
- data.tar.gz: 8764080e6a1c38b519110a8001b53ebda5864e7b16cdf418b272459542f60e1f
3
+ metadata.gz: 239a8df86c5fd746683d265f47f53ee415ac40613c8411abc8e4492cc3e02e18
4
+ data.tar.gz: 5614b247d018816964ab128923d4a86fd1fd4e6c397309bb74864c06a4ee95fd
5
5
  SHA512:
6
- metadata.gz: 0f43b198fc8050550fb78d3a96ad14dff765fdcce80b5ae73ce080e6fb13600697658cf3b9d2b73e1ed9adc0d40cedfb890047696778dc5e3770dead5889e666
7
- data.tar.gz: 6f30c6b07f81396b3f7366fd30186b83ddbf1ef474e375838c77df5a635b96bc2ac4dc4bf2036789a235f19efa3bc22ac76c246d31db9a697b8235790f045c4b
6
+ metadata.gz: fad2007fa5541c260baa72dd32527fba69ed292c7ec589959f023ef8a4edc206a1bb260dc0d3b6421586758f3d707c6284aac5c300d1dda00d30250d3f78c45f
7
+ data.tar.gz: cf384d7f97d445df492f9cb67737d852b725d63542d5da2bd30809a91a36c5277ea851c7502cda03724a13ab1eb2036122eaf4c1aeb5a661e25ec4bf81993cc7
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. Run the `release` task:
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
- if $0 == __FILE__
30
- parser.parse!
31
- success = command.run(ARGV.dup)
29
+ parser.parse!
30
+ success = command.run(ARGV.dup)
32
31
 
33
- if success
34
- command.messages.each { |m| $stdout.puts(m) }
35
- elsif !command.errors.empty?
36
- command.errors.each { |e| $stderr.puts(e) }
37
- exit(1)
38
- else
39
- print_usage!
40
- exit(1)
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
@@ -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 = schema.properties.dup
258
- if schema.properties && schema.properties.is_a?(Hash)
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
 
@@ -84,9 +84,26 @@ module JsonSchema
84
84
  end
85
85
  end
86
86
 
87
- def dereference(ref_schema, ref_stack)
87
+ def dereference(ref_schema, ref_stack, parent_ref: nil)
88
88
  ref = ref_schema.reference
89
89
 
90
+ # Some schemas don't have a reference, but do
91
+ # have children. If that's the case, we need to
92
+ # dereference the subschemas.
93
+ if !ref
94
+ schema_children(ref_schema) do |subschema|
95
+ next unless subschema.reference
96
+ next if ref_schema.uri == parent_ref.uri.to_s
97
+
98
+ if !subschema.reference.uri && parent_ref
99
+ subschema.reference = JsonReference::Reference.new("#{parent_ref.uri}#{subschema.reference.pointer}")
100
+ end
101
+
102
+ dereference(subschema, ref_stack)
103
+ end
104
+ return true
105
+ end
106
+
90
107
  # detects a reference cycle
91
108
  if ref_stack.include?(ref)
92
109
  message = %{Reference loop detected: #{ref_stack.sort.join(", ")}.}
@@ -110,22 +127,44 @@ module JsonSchema
110
127
  # references.
111
128
  if ref.uri
112
129
  schema_children(new_schema) do |subschema|
113
- next if subschema.expanded?
114
- next unless subschema.reference
115
-
116
130
  # Don't bother if the subschema points to the same
117
131
  # schema as the reference schema.
118
132
  next if ref_schema == subschema
119
133
 
120
- if !subschema.reference.uri
121
- # the subschema's ref is local to the file that the
122
- # subschema is in; however since there's no URI
123
- # the 'resolve_pointer' method would try to look it up
124
- # within @schema. So: manually reconstruct the reference to
125
- # use the URI of the parent ref.
126
- subschema.reference = JsonReference::Reference.new("#{ref.uri}#{subschema.reference.pointer}")
134
+ if subschema.reference
135
+ # If the subschema has a reference, then
136
+ # we don't need to recurse if the schema is
137
+ # already expanded.
138
+ next if subschema.expanded?
139
+
140
+ if !subschema.reference.uri
141
+ # the subschema's ref is local to the file that the
142
+ # subschema is in; however since there's no URI
143
+ # the 'resolve_pointer' method would try to look it up
144
+ # within @schema. So: manually reconstruct the reference to
145
+ # use the URI of the parent ref.
146
+ subschema.reference = JsonReference::Reference.new("#{ref.uri}#{subschema.reference.pointer}")
147
+ end
127
148
  end
128
- dereference(subschema, ref_stack)
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
+
161
+ # If we're recursing into a schema via a global reference, then if
162
+ # the current subschema doesn't have a reference, we have no way of
163
+ # figuring out what schema we're in. The resolve_pointer method will
164
+ # default to looking it up in the initial schema. Instead, we're
165
+ # passing the parent ref here, so we can grab the URI
166
+ # later if needed.
167
+ dereference(subschema, ref_stack, parent_ref: ref)
129
168
  end
130
169
  end
131
170
 
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 include our Ruby executables
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 because they're gated by `if
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
- load File.join(@bin_dir, "validate-schema")
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",
@@ -320,6 +401,136 @@ describe JsonSchema::ReferenceExpander do
320
401
  assert_equal 3, schema1.properties["foo"].properties["omg"].max_length
321
402
  end
322
403
 
404
+ it "it handles oneOf with nested references to an external schema" do
405
+ sample1 = {
406
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
407
+ "type" => "object",
408
+ "properties" => {
409
+ "foo" => {
410
+ "$ref" => "http://json-schema.org/b.json#"
411
+ }
412
+ }
413
+ }
414
+ schema1 = JsonSchema::Parser.new.parse!(sample1)
415
+ schema1.uri = "http://json-schema.org/a.json"
416
+
417
+ sample2 = {
418
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
419
+ "type" => "object",
420
+ "properties" => {
421
+ "bar" => {
422
+ "oneOf" => [
423
+ {"type" => "null"},
424
+ {"$ref" => "http://json-schema.org/c.json#"}
425
+ ]
426
+ }
427
+ },
428
+ }
429
+ schema2 = JsonSchema::Parser.new.parse!(sample2)
430
+ schema2.uri = "http://json-schema.org/b.json"
431
+
432
+ sample3 = {
433
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
434
+ "type" => "object",
435
+ "properties" => {
436
+ "baz" => {
437
+ "type" => "string",
438
+ "maxLength" => 3
439
+ }
440
+ }
441
+ }
442
+ schema3 = JsonSchema::Parser.new.parse!(sample3)
443
+ schema3.uri = "http://json-schema.org/c.json"
444
+
445
+ # Initialize a store and add our schema to it.
446
+ store = JsonSchema::DocumentStore.new
447
+ store.add_schema(schema1)
448
+ store.add_schema(schema2)
449
+ store.add_schema(schema3)
450
+
451
+ expander = JsonSchema::ReferenceExpander.new
452
+ expander.expand(schema1, store: store)
453
+
454
+ assert_equal 3, schema1.properties["foo"].properties["bar"].one_of[1].properties["baz"].max_length
455
+ end
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
+
489
+ it "it handles oneOf with nested references to a local schema" do
490
+ sample1 = {
491
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
492
+ "type" => "object",
493
+ "properties" => {
494
+ "foo" => {
495
+ "$ref" => "http://json-schema.org/b.json#"
496
+ }
497
+ }
498
+ }
499
+ schema1 = JsonSchema::Parser.new.parse!(sample1)
500
+ schema1.uri = "http://json-schema.org/a.json"
501
+
502
+ sample2 = {
503
+ "$schema" => "http://json-schema.org/draft-04/hyper-schema",
504
+ "type" => "object",
505
+ "definitions" => {
506
+ "baz" => {
507
+ "type" => "string",
508
+ "maxLength" => 3
509
+ }
510
+ },
511
+ "properties" => {
512
+ "bar" => {
513
+ "oneOf" => [
514
+ {"type" => "null"},
515
+ {"$ref" => "#/definitions/baz"}
516
+ ]
517
+ }
518
+ },
519
+ }
520
+ schema2 = JsonSchema::Parser.new.parse!(sample2)
521
+ schema2.uri = "http://json-schema.org/b.json"
522
+
523
+ # Initialize a store and add our schema to it.
524
+ store = JsonSchema::DocumentStore.new
525
+ store.add_schema(schema1)
526
+ store.add_schema(schema2)
527
+
528
+ expander = JsonSchema::ReferenceExpander.new
529
+ expander.expand(schema1, store: store)
530
+
531
+ assert_equal 3, schema1.properties["foo"].properties["bar"].one_of[1].max_length
532
+ end
533
+
323
534
  it "expands a schema with a reference to an external schema with a nested local property reference" do
324
535
  sample1 = {
325
536
  "$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.3
4
+ version: 0.20.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-23 00:00:00.000000000 Z
11
+ date: 2019-09-13 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
- rubyforge_project:
73
- rubygems_version: 2.7.7
72
+ rubygems_version: 3.0.6
74
73
  signing_key:
75
74
  specification_version: 4
76
75
  summary: A JSON Schema V4 and Hyperschema V4 parser and validator.