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 +8 -8
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +16 -4
- data/lib/openc/json_schema.rb +2 -2
- data/lib/openc/json_schema/validator.rb +74 -34
- data/lib/openc/json_schema/version.rb +1 -1
- data/openc-json_schema.gemspec +1 -1
- data/spec/openc_json_schema_spec.rb +112 -1
- data/spec/schemas/fff.json +7 -0
- data/spec/schemas/iii.json +7 -0
- data/spec/schemas/includes/ggg.json +6 -0
- data/spec/schemas/includes/hhh.json +8 -0
- data/spec/schemas/includes/jjj.json +6 -0
- data/spec/schemas/includes/mmm.json +6 -0
- data/spec/schemas/kkk.json +8 -0
- data/spec/schemas/lll.json +11 -0
- data/spec/spec_helper.rb +7 -6
- metadata +18 -16
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmE0MDA3M2IxMWZhMTlhZGU5MDdhNmMzNzJmMjA3MzYzZGI5MjE5Mg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjQyN2Q2YWYyMjgyYmJiZWJlN2YxMDk3MzU4ZWUzM2E5ZWMzZGI5ZA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTBjYTFhZTIyOWMyNzUzOTZkNTJkZTI5OTU2NzY4NWU0N2FiNzkxNWJiNjQ3
|
10
|
+
MTViOTg0ODVjZjg0YTY3MjdiMzExMzZjMjQxNDQyOWE2ZDJlNzI1NTk4Mjg2
|
11
|
+
ODI3YmRkZGJlMzg3NmMzZTBkNmM5ZTFmYTJkOTI0MmI4Njc5Yjg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTBjNjliN2EzOWUzZmRhMDcyMzk0ZDkyMzc4OWFkNzZjMzFhNjUxYTM0ZTNh
|
14
|
+
MjFiODNlYTVlMTVkYzdhMDgxNjY0MzllMThjZTRkOGFjM2ZhYTMxMWQ4NTA1
|
15
|
+
N2RmNmVjNWJlYWJkNmRkMGM2N2VhZTZlNzMwYjQ0YWFhMjk1ZWQ=
|
data/.gitignore
CHANGED
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.
|
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
|
-
|
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
|
data/lib/openc/json_schema.rb
CHANGED
@@ -7,8 +7,8 @@ module Openc
|
|
7
7
|
module JsonSchema
|
8
8
|
extend self
|
9
9
|
|
10
|
-
def validate(
|
11
|
-
Validator.validate(
|
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(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
27
|
-
|
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
|
-
|
33
|
-
|
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
|
-
|
38
|
-
|
28
|
+
json_schema = validator.instance_variable_get(:@base_schema)
|
29
|
+
schema = json_schema.schema
|
39
30
|
|
40
31
|
path_elements.each do |element|
|
41
|
-
|
42
|
-
|
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 =
|
42
|
+
one_of_schemas = schema['oneOf']
|
46
43
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
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'}
|
data/openc-json_schema.gemspec
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
9
|
-
File.open(
|
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
|
-
|
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(
|
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.
|
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-
|
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:
|