openc-json_schema 0.0.3 → 0.0.4

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWJiYzM4NmZlYzYxNzU5MmNjODQ0NTI3ODhmODcyNTAyZGU2MTZhNQ==
4
+ YmE0MDA3M2IxMWZhMTlhZGU5MDdhNmMzNzJmMjA3MzYzZGI5MjE5Mg==
5
5
  data.tar.gz: !binary |-
6
- NzFhYzk0MGQ0ODZlMWQ4Mjg4Njg0YjZkNWVlYWZiZDcyMGVhZjQzNw==
6
+ YjQyN2Q2YWYyMjgyYmJiZWJlN2YxMDk3MzU4ZWUzM2E5ZWMzZGI5ZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NjM0ZTVlZDRjZGVlY2NkMWQyZjQ1YWNiZDdmYzg1MmJjNTllZmNhOTgwYWNj
10
- M2NlNGE0OGM0MzJhY2I5MmE0ZDRmZWIzMDQzZjkwYjYwZmJmNTA5YzRlMzk1
11
- OGQyZjZmZDdjMGI4YWE1ODYzM2JkZGNmOWM5OGIwMTllY2VmNDE=
9
+ MTBjYTFhZTIyOWMyNzUzOTZkNTJkZTI5OTU2NzY4NWU0N2FiNzkxNWJiNjQ3
10
+ MTViOTg0ODVjZjg0YTY3MjdiMzExMzZjMjQxNDQyOWE2ZDJlNzI1NTk4Mjg2
11
+ ODI3YmRkZGJlMzg3NmMzZTBkNmM5ZTFmYTJkOTI0MmI4Njc5Yjg=
12
12
  data.tar.gz: !binary |-
13
- NTE0OWZhNWMwNTJkOGYxOGFmN2M0NWY2NzJlZWViYzczODM4YWZiMjc2YzE1
14
- MTgwZmQ0MTc0ZGNiYjBhZDFhNzI4NDM1NWQ0ZTlkMTA4MDRiZmM4MTljMWY3
15
- YTFkOWFhYWFmOWMxY2UzOGE3NzY2OWEwNGM4NjdiYThkZTg5YjU=
13
+ OTBjNjliN2EzOWUzZmRhMDcyMzk0ZDkyMzc4OWFkNzZjMzFhNjUxYTM0ZTNh
14
+ MjFiODNlYTVlMTVkYzdhMDgxNjY0MzllMThjZTRkOGFjM2ZhYTMxMWQ4NTA1
15
+ N2RmNmVjNWJlYWJkNmRkMGM2N2VhZTZlNzMwYjQ0YWFhMjk1ZWQ=
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  spec/tmp/*.json
2
+ coverage
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in openc-json-schema.gemspec
4
4
  gemspec
5
+
6
+ gem 'json-schema', :git => 'git://github.com/ruby-json-schema/json-schema.git', :ref => 'aded4d798a48545184dae7ae0a3bb41ec2794c88'
7
+
8
+ gem 'simplecov', :require => false
data/Gemfile.lock CHANGED
@@ -1,16 +1,22 @@
1
+ GIT
2
+ remote: git://github.com/ruby-json-schema/json-schema.git
3
+ revision: aded4d798a48545184dae7ae0a3bb41ec2794c88
4
+ ref: aded4d798a48545184dae7ae0a3bb41ec2794c88
5
+ specs:
6
+ json-schema (2.5.0)
7
+ addressable (~> 2.3)
8
+
1
9
  PATH
2
10
  remote: .
3
11
  specs:
4
- openc-json_schema (0.0.3)
5
- json-schema (= 2.5.0)
12
+ openc-json_schema (0.0.4)
6
13
 
7
14
  GEM
8
15
  remote: https://rubygems.org/
9
16
  specs:
10
17
  addressable (2.3.7)
11
18
  diff-lcs (1.2.5)
12
- json-schema (2.5.0)
13
- addressable (~> 2.3)
19
+ multi_json (1.10.1)
14
20
  rake (10.4.2)
15
21
  rspec (3.1.0)
16
22
  rspec-core (~> 3.1.0)
@@ -24,12 +30,18 @@ GEM
24
30
  rspec-mocks (3.1.3)
25
31
  rspec-support (~> 3.1.0)
26
32
  rspec-support (3.1.2)
33
+ simplecov (0.7.1)
34
+ multi_json (~> 1.0)
35
+ simplecov-html (~> 0.7.1)
36
+ simplecov-html (0.7.1)
27
37
 
28
38
  PLATFORMS
29
39
  ruby
30
40
 
31
41
  DEPENDENCIES
32
42
  bundler (~> 1.7)
43
+ json-schema!
33
44
  openc-json_schema!
34
45
  rake (~> 10.0)
35
46
  rspec (~> 3.0)
47
+ simplecov
@@ -7,8 +7,8 @@ module Openc
7
7
  module JsonSchema
8
8
  extend self
9
9
 
10
- def validate(schema_or_filename, schema_dir, record)
11
- Validator.validate(schema_or_filename, schema_dir, record)
10
+ def validate(schema_path, record)
11
+ Validator.validate(schema_path, record)
12
12
  end
13
13
  end
14
14
  end
@@ -3,64 +3,100 @@ module Openc
3
3
  module Validator
4
4
  extend self
5
5
 
6
- def validate(schema_or_filename, schema_dir, record)
7
- case schema_or_filename
8
- when Hash
9
- schema = schema_or_filename
10
- when String
11
- filename = schema_or_filename
12
- schema = JSON.parse(File.read(File.join(schema_dir, filename)))
13
- else
14
- raise TypeError.new("Unexpected value for schema_or_filename: #{schema_or_filename.class}")
15
- end
16
-
17
- # We must change directory for the relative paths in schemas to make sense.
18
- errors = Dir.chdir(schema_dir) do
19
- JSON::Validator.fully_validate(schema, record, :errors_as_objects => true)
20
- end
6
+ def validate(schema_path, record)
7
+ validator = JSON::Validator.new(
8
+ schema_path,
9
+ record,
10
+ :record_errors => true,
11
+ :errors_as_objects => true,
12
+ :validate_schema => true
13
+ )
14
+ errors = validator.validate
21
15
 
22
16
  # For now, we just handle the first error.
23
17
  error = errors[0]
24
18
  return if error.nil?
25
19
 
26
- case error[:failed_attribute]
27
- when 'Required'
28
- match = error[:message].match(/required property of '(.*)'/)
29
- missing_property = match[1]
30
- path = fragment_to_path("#{error[:fragment]}/#{missing_property}")
20
+ convert_error(extract_error(error, record, validator))
21
+ end
31
22
 
32
- {:type => :missing, :path => path}
33
- when 'OneOf'
23
+ def extract_error(error, record, validator)
24
+ if error[:failed_attribute] == 'OneOf'
34
25
  if error[:message].match(/did not match any/)
35
26
  path_elements = fragment_to_path(error[:fragment]).split('.')
36
27
 
37
- record_fragment = record
38
- schema_fragment = schema
28
+ json_schema = validator.instance_variable_get(:@base_schema)
29
+ schema = json_schema.schema
39
30
 
40
31
  path_elements.each do |element|
41
- record_fragment = record_fragment[element]
42
- schema_fragment = schema_fragment['properties'][element]
32
+ record = record[element]
33
+ schema = schema['properties'][element]
34
+
35
+ if (ref = schema['$ref'])
36
+ schema_uri = validator.absolutize_ref_uri(ref, json_schema.uri)
37
+ json_schema = JSON::Validator.schema_reader.read(schema_uri)
38
+ schema = json_schema.schema
39
+ end
43
40
  end
44
41
 
45
- one_of_schemas = schema_fragment['oneOf']
42
+ one_of_schemas = schema['oneOf']
46
43
 
47
- unless one_of_schemas.nil?
48
- one_of_schemas.each do |s|
49
- s['properties'].each do |k, v|
50
- next if v['enum'].nil?
44
+ schemas_for_type_with_ix = case record
45
+ when Hash
46
+ one_of_schemas.each_with_index.reject {|s, ix| s['properties'].nil?}
47
+ when String
48
+ one_of_schemas.each_with_index.select {|s, ix| s['type'] == 'string' || (s['type'].nil? && s['properties'].nil?)}
49
+ when Integer
50
+ one_of_schemas.each_with_index.select {|s, ix| s['type'] == 'integer'}
51
+ when Array
52
+ one_of_schemas.each_with_index.select {|s, ix| s['type'] == 'array'}
53
+ else
54
+ raise "Unexpected type: #{record}"
55
+ end
51
56
 
52
- if v['enum'].include?(record_fragment[k])
53
- error1 = validate(s, schema_dir, record_fragment)
54
- return error1.merge(:path => "#{path_elements.join('.')}.#{error1[:path]}")
57
+ case schemas_for_type_with_ix.size
58
+ when 0
59
+ return error
60
+ when 1
61
+ ix = schemas_for_type_with_ix[0][1]
62
+ return error[:errors][:"oneof_#{ix}"][0]
63
+ else
64
+ if record.is_a?(Hash)
65
+ schemas_for_type_with_ix.each do |s, ix|
66
+ s['properties'].each do |k, v|
67
+ next if v['enum'].nil?
68
+
69
+ if v['enum'].include?(record[k])
70
+ return error[:errors][:"oneof_#{ix}"][0]
71
+ end
55
72
  end
56
73
  end
74
+ else
75
+ return error
57
76
  end
58
77
  end
78
+ end
79
+ end
80
+
81
+ error
82
+ end
83
+
84
+ def convert_error(error)
85
+ case error[:failed_attribute]
86
+ when 'Required'
87
+ match = error[:message].match(/required property of '(.*)'/)
88
+ missing_property = match[1]
89
+ path = fragment_to_path("#{error[:fragment]}/#{missing_property}")
59
90
 
91
+ {:type => :missing, :path => path}
92
+ when 'OneOf'
93
+ if error[:message].match(/did not match any/)
60
94
  {:type => :one_of_no_matches, :path => fragment_to_path(error[:fragment])}
61
95
  else
62
96
  {:type => :one_of_many_matches, :path => fragment_to_path(error[:fragment])}
63
97
  end
98
+ when 'AnyOf'
99
+ {:type => :any_of_no_matches, :path => fragment_to_path(error[:fragment])}
64
100
  when 'MinLength'
65
101
  match = error[:message].match(/minimum string length of (\d+) in/)
66
102
  min_length = match[1].to_i
@@ -77,6 +113,10 @@ module Openc
77
113
  match = error[:message].match(/the following values: ([\w\s,]+) in schema/)
78
114
  allowed_values = match[1].split(',').map(&:strip)
79
115
  {:type => :enum_mismatch, :path => fragment_to_path(error[:fragment]), :allowed_values => allowed_values}
116
+ when 'AdditionalProperties'
117
+ match = error[:message].match(/contains additional properties \["(.*)"\] outside of the schema/)
118
+ extra_properties = match[1].split('", "')
119
+ {:type => :extra_properties, :path => fragment_to_path(error[:fragment]), :extra_properties => extra_properties}
80
120
  else
81
121
  if error[:message].match(/must be of format yyyy-mm-dd/)
82
122
  {:type => :format_mismatch, :path => fragment_to_path(error[:fragment]), :expected_format => 'yyyy-mm-dd'}
@@ -1,5 +1,5 @@
1
1
  module Openc
2
2
  module JsonSchema
3
- VERSION = '0.0.3'
3
+ VERSION = '0.0.4'
4
4
  end
5
5
  end
@@ -21,5 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "rake", "~> 10.0"
22
22
  spec.add_development_dependency "rspec", "~> 3.0"
23
23
 
24
- spec.add_dependency "json-schema", "2.5.0"
24
+ # spec.add_dependency "json-schema", "2.5.0"
25
25
  end
@@ -277,6 +277,25 @@ describe Openc::JsonSchema do
277
277
  )
278
278
  end
279
279
 
280
+ specify 'when additional properties are present but disallowed' do
281
+ schema = {
282
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
283
+ 'type' => 'object',
284
+ 'properties' => {
285
+ 'aaa' => {'type' => 'number'}
286
+ },
287
+ 'additionalProperties' => false
288
+ }
289
+
290
+ record = {'aaa' => 1, 'bbb' => 2, 'ccc' => 3}
291
+
292
+ expect([schema, record]).to fail_validation_with(
293
+ :type => :extra_properties,
294
+ :path => '',
295
+ :extra_properties => ['bbb', 'ccc']
296
+ )
297
+ end
298
+
280
299
  specify 'when property of wrong format' do
281
300
  schema = {
282
301
  '$schema' => 'http://json-schema.org/draft-04/schema#',
@@ -329,7 +348,72 @@ describe Openc::JsonSchema do
329
348
  end
330
349
  end
331
350
 
332
- specify 'when schema includes oneOfs which contain $refs' do
351
+ context 'when schema includes nested $refs' do
352
+ specify 'when data is valid' do
353
+ schema_path = 'spec/schemas/fff.json'
354
+ record = {'fff' => {'ggg' => {'hhh' => 123}}}
355
+ expect([schema_path, record]).to be_valid
356
+ end
357
+
358
+ specify 'when data is invalid' do
359
+ schema_path = 'spec/schemas/fff.json'
360
+ record = {'fff' => {'ggg' => {'hhh' => '123'}}}
361
+ expect([schema_path, record]).to fail_validation_with(
362
+ :type => :type_mismatch,
363
+ :path => 'fff.ggg.hhh',
364
+ :allowed_types => ['number']
365
+ )
366
+ end
367
+
368
+ context 'and schema is an included schema' do
369
+ specify 'when data is valid' do
370
+ schema_path = 'spec/schemas/includes/ggg.json'
371
+ record = {'ggg' => {'hhh' => 123}}
372
+ expect([schema_path, record]).to be_valid
373
+ end
374
+
375
+ specify 'when data is invalid' do
376
+ schema_path = 'spec/schemas/includes/ggg.json'
377
+ record = {'ggg' => {'hhh' => '123'}}
378
+ expect([schema_path, record]).to fail_validation_with(
379
+ :type => :type_mismatch,
380
+ :path => 'ggg.hhh',
381
+ :allowed_types => ['number']
382
+ )
383
+ end
384
+ end
385
+
386
+ context 'and there is a $ref to something in an outer directory' do
387
+ specify 'when data is valid' do
388
+ schema_path = 'spec/schemas/iii.json'
389
+ record = {'iii' => {'jjj' => {'kkk' => 123}}}
390
+ expect([schema_path, record]).to be_valid
391
+ end
392
+
393
+ specify 'when data is invalid' do
394
+ schema_path = 'spec/schemas/iii.json'
395
+ record = {'iii' => {'jjj' => {'kkk' => '123'}}}
396
+ expect([schema_path, record]).to fail_validation_with(
397
+ :type => :type_mismatch,
398
+ :path => 'iii.jjj.kkk',
399
+ :allowed_types => ['number']
400
+ )
401
+ end
402
+ end
403
+ end
404
+
405
+ specify 'when schema includes oneOfs which contain $refs directly' do
406
+ schema_path = 'spec/schemas/lll.json'
407
+ record = {
408
+ 'mmm' => []
409
+ }
410
+ expect([schema_path, record]).to fail_validation_with(
411
+ :type => :one_of_no_matches,
412
+ :path => 'mmm'
413
+ )
414
+ end
415
+
416
+ specify 'when schema includes oneOfs which contain $refs indirectly' do
333
417
  schema_path = 'spec/schemas/ccc.json'
334
418
  record = {
335
419
  'ccc' => {
@@ -345,5 +429,32 @@ describe Openc::JsonSchema do
345
429
  :allowed_types => ['number'],
346
430
  )
347
431
  end
432
+
433
+ specify '' do
434
+ schema = {
435
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
436
+ 'type' => 'object',
437
+ 'properties' => {
438
+ 'aaa' => {
439
+ 'oneOf' => [
440
+ {
441
+ 'type' => 'string',
442
+ 'format' => 'date'
443
+ },
444
+ {
445
+ 'type' => 'integer',
446
+ 'maxLength' => 2
447
+ }
448
+ ]
449
+ }
450
+ }
451
+ }
452
+ record = {'aaa' => 'not-a-date'}
453
+ expect([schema, record]).to fail_validation_with(
454
+ :type => :format_mismatch,
455
+ :path => 'aaa',
456
+ :expected_format => 'yyyy-mm-dd'
457
+ )
458
+ end
348
459
  end
349
460
  end
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "fff": {"$ref": "includes/ggg.json"}
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "iii": {"$ref": "includes/jjj.json"}
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "ggg": {"$ref": "hhh.json"}
5
+ }
6
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "hhh": {
5
+ "type": "number"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "jjj": {"$ref": "../kkk.json"}
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "oneOf": [
3
+ {"type": "integer"},
4
+ {"type": "string"}
5
+ ]
6
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "kkk": {
5
+ "type": "number"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "mmm": {
6
+ "$ref": "includes/mmm.json"
7
+ }
8
+ },
9
+ "additionalProperties": false
10
+ }
11
+
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
1
4
  require 'openc/json_schema'
2
5
 
3
6
  def get_error(schema_or_path, record)
@@ -5,17 +8,15 @@ def get_error(schema_or_path, record)
5
8
  when Hash
6
9
  json_data = schema_or_path.to_json
7
10
  filename = Digest::MD5.hexdigest(json_data) + '.json'
8
- schema_dir = "spec/tmp"
9
- File.open(File.join(schema_dir, filename), 'w') {|f| f.write(json_data)}
10
- schema_or_filename = schema_or_path
11
+ schema_path = File.join('spec', 'tmp', filename)
12
+ File.open(schema_path, 'w') {|f| f.write(json_data)}
11
13
  when String
12
- schema_or_filename = File.basename(schema_or_path)
13
- schema_dir = File.dirname(schema_or_path)
14
+ schema_path = schema_or_path
14
15
  else
15
16
  raise
16
17
  end
17
18
 
18
- error = Openc::JsonSchema.validate(schema_or_filename, schema_dir, record)
19
+ error = Openc::JsonSchema.validate(schema_path, record)
19
20
  end
20
21
 
21
22
  RSpec::Matchers.define(:fail_validation_with) do |expected|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openc-json_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenCorporates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-05 00:00:00.000000000 Z
11
+ date: 2015-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
- - !ruby/object:Gem::Dependency
56
- name: json-schema
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - '='
60
- - !ruby/object:Gem::Version
61
- version: 2.5.0
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - '='
67
- - !ruby/object:Gem::Version
68
- version: 2.5.0
69
55
  description:
70
56
  email: info@opencorporates.com
71
57
  executables: []
@@ -87,9 +73,17 @@ files:
87
73
  - spec/openc_json_schema_spec.rb
88
74
  - spec/schemas/aaa.json
89
75
  - spec/schemas/ccc.json
76
+ - spec/schemas/fff.json
77
+ - spec/schemas/iii.json
90
78
  - spec/schemas/includes/bbb.json
91
79
  - spec/schemas/includes/ddd.json
92
80
  - spec/schemas/includes/eee.json
81
+ - spec/schemas/includes/ggg.json
82
+ - spec/schemas/includes/hhh.json
83
+ - spec/schemas/includes/jjj.json
84
+ - spec/schemas/includes/mmm.json
85
+ - spec/schemas/kkk.json
86
+ - spec/schemas/lll.json
93
87
  - spec/spec_helper.rb
94
88
  - spec/tmp/.gitkeep
95
89
  homepage:
@@ -120,9 +114,17 @@ test_files:
120
114
  - spec/openc_json_schema_spec.rb
121
115
  - spec/schemas/aaa.json
122
116
  - spec/schemas/ccc.json
117
+ - spec/schemas/fff.json
118
+ - spec/schemas/iii.json
123
119
  - spec/schemas/includes/bbb.json
124
120
  - spec/schemas/includes/ddd.json
125
121
  - spec/schemas/includes/eee.json
122
+ - spec/schemas/includes/ggg.json
123
+ - spec/schemas/includes/hhh.json
124
+ - spec/schemas/includes/jjj.json
125
+ - spec/schemas/includes/mmm.json
126
+ - spec/schemas/kkk.json
127
+ - spec/schemas/lll.json
126
128
  - spec/spec_helper.rb
127
129
  - spec/tmp/.gitkeep
128
130
  has_rdoc: