json_schema 0.20.3 → 0.20.8

Sign up to get free protection for your applications and to get access to all the features.
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.