json-schema 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,7 +18,7 @@ From the git repo:
18
18
 
19
19
  <pre>
20
20
  $ gem build json-schema.gemspec
21
- $ gem install json-schema-1.0.8.gem
21
+ $ gem install json-schema-1.0.9.gem
22
22
  </pre>
23
23
 
24
24
 
@@ -1,3 +1,5 @@
1
+ require_relative 'extends'
2
+
1
3
  module JSON
2
4
  class Schema
3
5
  class AdditionalPropertiesAttribute < Attribute
@@ -5,6 +7,28 @@ module JSON
5
7
  if data.is_a?(Hash)
6
8
  extra_properties = data.keys
7
9
 
10
+ extra_properties = remove_valid_properties(extra_properties, current_schema, validator)
11
+
12
+ addprop= current_schema.schema['additionalProperties']
13
+ if addprop.is_a?(Hash)
14
+ matching_properties= extra_properties # & addprop.keys
15
+ matching_properties.each do |key|
16
+ schema = JSON::Schema.new(addprop[key] || addprop, current_schema.uri, validator)
17
+ fragments << key
18
+ schema.validate(data[key],fragments,options)
19
+ fragments.pop
20
+ end
21
+ extra_properties -= matching_properties
22
+ end
23
+ if !extra_properties.empty? and (addprop == false or (addprop.is_a?(Hash) and !addprop.empty?))
24
+ message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
25
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.remove_valid_properties(extra_properties, current_schema, validator)
31
+
8
32
  if current_schema.schema['properties']
9
33
  extra_properties = extra_properties - current_schema.schema['properties'].keys
10
34
  end
@@ -21,19 +45,18 @@ module JSON
21
45
  end
22
46
  end
23
47
 
24
- if current_schema.schema['additionalProperties'] == false && !extra_properties.empty?
25
- message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
26
- validation_error(message, fragments, current_schema, self, options[:record_errors])
27
- elsif current_schema.schema['additionalProperties'].is_a?(Hash)
28
- extra_properties.each do |key|
29
- schema = JSON::Schema.new(current_schema.schema['additionalProperties'],current_schema.uri,validator)
30
- fragments << key
31
- schema.validate(data[key],fragments,options)
32
- fragments.pop
48
+ if schemas= current_schema.schema['extends']
49
+ schemas = [schemas] if !schemas.is_a?(Array)
50
+ schemas.each do |schema_value|
51
+ temp_uri,extended_schema= JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator)
52
+ if extended_schema
53
+ extra_properties= remove_valid_properties(extra_properties, extended_schema, validator)
54
+ end
33
55
  end
34
56
  end
35
- end
57
+
58
+ extra_properties
36
59
  end
37
60
  end
38
61
  end
39
- end
62
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'ref'
2
+
1
3
  module JSON
2
4
  class Schema
3
5
  class ExtendsAttribute < Attribute
@@ -5,63 +7,43 @@ module JSON
5
7
  schemas = current_schema.schema['extends']
6
8
  schemas = [schemas] if !schemas.is_a?(Array)
7
9
  schemas.each do |s|
8
- if s.is_a?(Hash)
9
- schema = JSON::Schema.new(s,current_schema.uri,validator)
10
+ uri,schema = get_extended_uri_and_schema(s, current_schema, validator)
11
+ if schema
10
12
  schema.validate(data, fragments, options)
11
- elsif s.is_a?(String)
12
- temp_uri = URI.parse(s)
13
- if temp_uri.relative?
14
- temp_uri = current_schema.uri.clone
15
- # Check for absolute path
16
- path = s.split("#")[0]
17
- if path.nil? || path == ''
18
- temp_uri.path = current_schema.uri.path
19
- elsif path[0,1] == "/"
20
- temp_uri.path = Pathname.new(path).cleanpath.to_s
21
- else
22
- temp_uri = current_schema.uri.merge(path)
23
- end
24
- temp_uri.fragment = s.split("#")[1]
25
- end
26
- temp_uri.fragment = "" if temp_uri.fragment.nil?
13
+ elsif uri
14
+ message = "The extended schema '#{uri.to_s}' cannot be found"
15
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
16
+ else
17
+ message = "The property '#{build_fragment(fragments)}' was not a valid schema"
18
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
19
+ end
20
+ end
21
+ end
27
22
 
28
- # Grab the parent schema from the schema list
29
- schema_key = temp_uri.to_s.split("#")[0] + "#"
23
+ def self.get_extended_uri_and_schema(s, current_schema, validator)
24
+ uri,schema = nil,nil
30
25
 
31
- ref_schema = JSON::Validator.schemas[schema_key]
26
+ s = {'$ref' => s} if s.is_a?(String)
32
27
 
28
+ if s.is_a?(Hash)
29
+ uri = current_schema.uri
30
+ if s['$ref']
31
+ ref_uri,ref_schema = JSON::Schema::RefAttribute.get_referenced_uri_and_schema(s, current_schema, validator)
33
32
  if ref_schema
34
- # Perform fragment resolution to retrieve the appropriate level for the schema
35
- target_schema = ref_schema.schema
36
- fragments = temp_uri.fragment.split("/")
37
- fragment_path = ''
38
- fragments.each do |fragment|
39
- if fragment && fragment != ''
40
- if target_schema.is_a?(Array)
41
- target_schema = target_schema[fragment.to_i]
42
- else
43
- target_schema = target_schema[fragment]
44
- end
45
- fragment_path = fragment_path + "/#{fragment}"
46
- if target_schema.nil?
47
- raise SchemaError.new("The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri.to_s}")
48
- end
49
- end
33
+ if s.size == 1 # Check if anything else apart from $ref
34
+ uri,schema = ref_uri,ref_schema
35
+ else
36
+ s = s.dup
37
+ s.delete '$ref'
38
+ s = ref_schema.schema.merge(s)
50
39
  end
51
-
52
- # We have the schema finally, build it and validate!
53
- schema = JSON::Schema.new(target_schema,temp_uri,validator)
54
- schema.validate(data, fragments, options)
55
- else
56
- message = "The extended schema '#{temp_uri.to_s}' cannot be found"
57
- validation_error(message, fragments, current_schema, self, options[:record_errors])
58
40
  end
59
- else
60
- message = "The property '#{build_fragment(fragments)}' was not a valid schema"
61
- validation_error(message, fragments, current_schema, self, options[:record_errors])
62
41
  end
42
+ schema ||= JSON::Schema.new(s,uri,validator)
63
43
  end
44
+
45
+ [uri,schema]
64
46
  end
65
47
  end
66
48
  end
67
- end
49
+ end
@@ -1,12 +1,28 @@
1
1
  module JSON
2
2
  class Schema
3
3
  class RefAttribute < Attribute
4
- def self.validate(current_schema, data, fragments, validator, options = {})
5
- temp_uri = URI.parse(current_schema.schema['$ref'])
4
+ def self.validate(current_schema, data, fragments, validator, options = {})
5
+ uri,schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)
6
+
7
+ if schema
8
+ schema.validate(data, fragments, options)
9
+ elsif uri
10
+ message = "The referenced schema '#{uri.to_s}' cannot be found"
11
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
12
+ else
13
+ message = "The property '#{build_fragment(fragments)}' was not a valid schema"
14
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
15
+ end
16
+ end
17
+
18
+ def self.get_referenced_uri_and_schema(s, current_schema, validator)
19
+ uri,schema = nil,nil
20
+
21
+ temp_uri = URI.parse(s['$ref'])
6
22
  if temp_uri.relative?
7
23
  temp_uri = current_schema.uri.clone
8
24
  # Check for absolute path
9
- path = current_schema.schema['$ref'].split("#")[0]
25
+ path = s['$ref'].split("#")[0]
10
26
  if path.nil? || path == ''
11
27
  temp_uri.path = current_schema.uri.path
12
28
  elsif path[0,1] == "/"
@@ -14,7 +30,7 @@ module JSON
14
30
  else
15
31
  temp_uri = current_schema.uri.merge(path)
16
32
  end
17
- temp_uri.fragment = current_schema.schema['$ref'].split("#")[1]
33
+ temp_uri.fragment = s['$ref'].split("#")[1]
18
34
  end
19
35
  temp_uri.fragment = "" if temp_uri.fragment.nil?
20
36
 
@@ -43,12 +59,11 @@ module JSON
43
59
  end
44
60
 
45
61
  # We have the schema finally, build it and validate!
62
+ uri = temp_uri
46
63
  schema = JSON::Schema.new(target_schema,temp_uri,validator)
47
- schema.validate(data, fragments, options)
48
- else
49
- message = "The referenced schema '#{temp_uri.to_s}' cannot be found"
50
- validation_error(message, fragments, current_schema, self, options[:record_errors])
51
64
  end
65
+
66
+ [uri,schema]
52
67
  end
53
68
  end
54
69
  end
@@ -407,7 +407,7 @@ module JSON
407
407
 
408
408
  def parse(s)
409
409
  if defined?(MultiJson)
410
- MultiJson.respond_to?(:load) ? MultiJson.load(s) : MultiJson.decode(s)
410
+ MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
411
411
  else
412
412
  case @@json_backend.to_s
413
413
  when 'json'
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "type": "object",
4
+ "extends": "inner.schema.json",
5
+ "properties": {
6
+ "outerA": {
7
+ "description": "blah",
8
+ "required": false,
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "outerA1": {
12
+ "type":"boolean",
13
+ "required": false
14
+ }
15
+ }
16
+ },
17
+ "outerB": {
18
+ "required": false,
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "maxItems": 50,
22
+ "items": {
23
+ "extends": "inner.schema.json",
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "outerC": {
28
+ "description": "blah",
29
+ "type":"boolean",
30
+ "required": false
31
+ }
32
+ },
33
+ "additionalProperties": false
34
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "type": "object",
4
+ "extends": {"$ref":"inner.schema.json#"},
5
+ "properties": {
6
+ "outerA": {
7
+ "description": "blah",
8
+ "required": false,
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "outerA1": {
12
+ "type":"boolean",
13
+ "required": false
14
+ }
15
+ }
16
+ },
17
+ "outerB": {
18
+ "required": false,
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "maxItems": 50,
22
+ "items": {
23
+ "extends": {"$ref":"inner.schema.json#"},
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "outerC": {
28
+ "description": "blah",
29
+ "type":"boolean",
30
+ "required": false
31
+ }
32
+ },
33
+ "additionalProperties": false
34
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "type": "object",
4
+ "extends": "inner.schema.json",
5
+ "additionalProperties": {
6
+ "outerA": {
7
+ "description": "blah",
8
+ "required": false,
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "outerA1": {
12
+ "type":"boolean",
13
+ "required": false
14
+ }
15
+ }
16
+ },
17
+ "outerB": {
18
+ "required": false,
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "maxItems": 50,
22
+ "items": {
23
+ "extends": "inner.schema.json",
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "outerC": {
28
+ "description": "blah",
29
+ "type":"boolean",
30
+ "required": false
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "type": "object",
4
+ "extends": {"$ref":"inner.schema.json#"},
5
+ "additionalProperties": {
6
+ "outerA": {
7
+ "description": "blah",
8
+ "required": false,
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "outerA1": {
12
+ "type":"boolean",
13
+ "required": false
14
+ }
15
+ }
16
+ },
17
+ "outerB": {
18
+ "required": false,
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "maxItems": 50,
22
+ "items": {
23
+ "extends": {"$ref":"inner.schema.json#"},
24
+ "additionalProperties": false
25
+ }
26
+ },
27
+ "outerC": {
28
+ "description": "blah",
29
+ "type":"boolean",
30
+ "required": false
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "innerA": {
6
+ "description": "blah",
7
+ "type":"boolean",
8
+ "required": false
9
+ },
10
+ "innerB": {
11
+ "description": "blah",
12
+ "type":"boolean",
13
+ "required": false
14
+ },
15
+ "innerC": {
16
+ "description": "blah",
17
+ "required": false,
18
+ "type": "boolean"
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,50 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/json-schema'
3
+
4
+ class ExtendsNestedTest < Test::Unit::TestCase
5
+
6
+ def assert_validity(valid, schema_name, data, msg=nil)
7
+ file = File.expand_path("../schemas/#{schema_name}.schema.json",__FILE__)
8
+ errors = JSON::Validator.fully_validate file, data
9
+ msg.sub! /\.$/, '' if msg
10
+ send (valid ? :assert_equal : :refute_equal), [], errors, \
11
+ "Schema should be #{valid ? :valid : :invalid}#{msg ? ".\n[#{schema_name}] #{msg}" : ''}"
12
+ end
13
+
14
+ def assert_valid(schema_name, data, msg=nil) assert_validity true, schema_name, data, msg end
15
+ def refute_valid(schema_name, data, msg=nil) assert_validity false, schema_name, data, msg end
16
+
17
+ %w[
18
+ extends_and_additionalProperties-1-filename extends_and_additionalProperties-1-ref
19
+ extends_and_additionalProperties-2-filename extends_and_additionalProperties-2-ref
20
+ ].each do |schema_name|
21
+ test_prefix= 'test_' + schema_name.gsub('-','_')
22
+ class_eval <<-EOB
23
+
24
+ def #{test_prefix}_valid_outer
25
+ assert_valid '#{schema_name}', {"outerC"=>true}, "Outer defn is broken, maybe the outer extends overrode it?"
26
+ end
27
+
28
+ def #{test_prefix}_valid_outer_extended
29
+ assert_valid '#{schema_name}', {"innerA"=>true}, "Extends at the root level isn't working."
30
+ end
31
+
32
+ def #{test_prefix}_valid_inner
33
+ assert_valid '#{schema_name}', {"outerB"=>[{"innerA"=>true}]}, "Extends isn't working in the array element defn."
34
+ end
35
+
36
+ def #{test_prefix}_invalid_inner
37
+ refute_valid '#{schema_name}', {"outerB"=>[{"whaaaaat"=>true}]}, "Array element defn allowing anything when it should only allow what's in inner.schema"
38
+ end
39
+ EOB
40
+
41
+ if schema_name['extends_and_additionalProperties-1']
42
+ class_eval <<-EOB
43
+ def #{test_prefix}_invalid_outer
44
+ refute_valid '#{schema_name}', {"whaaaaat"=>true}, "Outer defn allowing anything when it shouldn't."
45
+ end
46
+ EOB
47
+ end
48
+
49
+ end
50
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-13 00:00:00.000000000 Z
12
+ date: 2012-08-29 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: hoxworth@gmail.com
@@ -58,6 +58,7 @@ files:
58
58
  - README.textile
59
59
  - LICENSE.md
60
60
  - test/test_extended_schema.rb
61
+ - test/test_extends_and_additionalProperties.rb
61
62
  - test/test_files.rb
62
63
  - test/test_full_validation.rb
63
64
  - test/test_jsonschema_draft1.rb
@@ -66,8 +67,13 @@ files:
66
67
  - test/test_schema_validation.rb
67
68
  - test/data/bad_data_1.json
68
69
  - test/data/good_data_1.json
70
+ - test/schemas/extends_and_additionalProperties-1-filename.schema.json
71
+ - test/schemas/extends_and_additionalProperties-1-ref.schema.json
72
+ - test/schemas/extends_and_additionalProperties-2-filename.schema.json
73
+ - test/schemas/extends_and_additionalProperties-2-ref.schema.json
69
74
  - test/schemas/good_schema_1.json
70
75
  - test/schemas/good_schema_2.json
76
+ - test/schemas/inner.schema.json
71
77
  homepage: http://github.com/hoxworth/json-schema/tree/master
72
78
  licenses: []
73
79
  post_install_message:
@@ -88,12 +94,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
94
  version: '0'
89
95
  requirements: []
90
96
  rubyforge_project:
91
- rubygems_version: 1.8.10
97
+ rubygems_version: 1.8.24
92
98
  signing_key:
93
99
  specification_version: 3
94
100
  summary: Ruby JSON Schema Validator
95
101
  test_files:
96
102
  - test/test_extended_schema.rb
103
+ - test/test_extends_and_additionalProperties.rb
97
104
  - test/test_files.rb
98
105
  - test/test_full_validation.rb
99
106
  - test/test_jsonschema_draft1.rb
@@ -102,5 +109,11 @@ test_files:
102
109
  - test/test_schema_validation.rb
103
110
  - test/data/bad_data_1.json
104
111
  - test/data/good_data_1.json
112
+ - test/schemas/extends_and_additionalProperties-1-filename.schema.json
113
+ - test/schemas/extends_and_additionalProperties-1-ref.schema.json
114
+ - test/schemas/extends_and_additionalProperties-2-filename.schema.json
115
+ - test/schemas/extends_and_additionalProperties-2-ref.schema.json
105
116
  - test/schemas/good_schema_1.json
106
117
  - test/schemas/good_schema_2.json
118
+ - test/schemas/inner.schema.json
119
+ has_rdoc: