json-schema-pvdgm 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +19 -0
  3. data/README.textile +354 -0
  4. data/lib/json-schema.rb +25 -0
  5. data/lib/json-schema/attributes/additionalitems.rb +23 -0
  6. data/lib/json-schema/attributes/additionalproperties.rb +67 -0
  7. data/lib/json-schema/attributes/allof.rb +37 -0
  8. data/lib/json-schema/attributes/anyof.rb +41 -0
  9. data/lib/json-schema/attributes/dependencies.rb +30 -0
  10. data/lib/json-schema/attributes/dependencies_v4.rb +20 -0
  11. data/lib/json-schema/attributes/disallow.rb +11 -0
  12. data/lib/json-schema/attributes/divisibleby.rb +16 -0
  13. data/lib/json-schema/attributes/enum.rb +24 -0
  14. data/lib/json-schema/attributes/extends.rb +49 -0
  15. data/lib/json-schema/attributes/format.rb +123 -0
  16. data/lib/json-schema/attributes/items.rb +25 -0
  17. data/lib/json-schema/attributes/maxdecimal.rb +15 -0
  18. data/lib/json-schema/attributes/maximum.rb +15 -0
  19. data/lib/json-schema/attributes/maximum_inclusive.rb +15 -0
  20. data/lib/json-schema/attributes/maxitems.rb +12 -0
  21. data/lib/json-schema/attributes/maxlength.rb +14 -0
  22. data/lib/json-schema/attributes/maxproperties.rb +12 -0
  23. data/lib/json-schema/attributes/minimum.rb +15 -0
  24. data/lib/json-schema/attributes/minimum_inclusive.rb +15 -0
  25. data/lib/json-schema/attributes/minitems.rb +12 -0
  26. data/lib/json-schema/attributes/minlength.rb +14 -0
  27. data/lib/json-schema/attributes/minproperties.rb +12 -0
  28. data/lib/json-schema/attributes/multipleof.rb +16 -0
  29. data/lib/json-schema/attributes/not.rb +28 -0
  30. data/lib/json-schema/attributes/oneof.rb +32 -0
  31. data/lib/json-schema/attributes/pattern.rb +15 -0
  32. data/lib/json-schema/attributes/patternproperties.rb +23 -0
  33. data/lib/json-schema/attributes/properties.rb +58 -0
  34. data/lib/json-schema/attributes/properties_optional.rb +23 -0
  35. data/lib/json-schema/attributes/properties_v4.rb +57 -0
  36. data/lib/json-schema/attributes/ref.rb +70 -0
  37. data/lib/json-schema/attributes/required.rb +23 -0
  38. data/lib/json-schema/attributes/type.rb +102 -0
  39. data/lib/json-schema/attributes/type_v4.rb +54 -0
  40. data/lib/json-schema/attributes/uniqueitems.rb +16 -0
  41. data/lib/json-schema/model_validator.rb +85 -0
  42. data/lib/json-schema/schema.rb +73 -0
  43. data/lib/json-schema/uri/file.rb +36 -0
  44. data/lib/json-schema/uri/uuid.rb +285 -0
  45. data/lib/json-schema/util/array_set.rb +14 -0
  46. data/lib/json-schema/util/hash.rb +8 -0
  47. data/lib/json-schema/validator.rb +672 -0
  48. data/lib/json-schema/validators/draft1.rb +32 -0
  49. data/lib/json-schema/validators/draft2.rb +33 -0
  50. data/lib/json-schema/validators/draft3.rb +38 -0
  51. data/lib/json-schema/validators/draft4.rb +45 -0
  52. data/resources/draft-01.json +155 -0
  53. data/resources/draft-02.json +166 -0
  54. data/resources/draft-03.json +174 -0
  55. data/resources/draft-04.json +150 -0
  56. data/test/data/all_of_ref_data.json +3 -0
  57. data/test/data/any_of_ref_data.json +7 -0
  58. data/test/data/bad_data_1.json +3 -0
  59. data/test/data/good_data_1.json +3 -0
  60. data/test/data/one_of_ref_links_data.json +5 -0
  61. data/test/schemas/all_of_ref_base_schema.json +6 -0
  62. data/test/schemas/all_of_ref_schema.json +7 -0
  63. data/test/schemas/any_of_ref_jane_schema.json +4 -0
  64. data/test/schemas/any_of_ref_jimmy_schema.json +4 -0
  65. data/test/schemas/any_of_ref_john_schema.json +4 -0
  66. data/test/schemas/any_of_ref_schema.json +15 -0
  67. data/test/schemas/extends_and_additionalProperties-1-filename.schema.json +34 -0
  68. data/test/schemas/extends_and_additionalProperties-1-ref.schema.json +34 -0
  69. data/test/schemas/extends_and_additionalProperties-2-filename.schema.json +33 -0
  70. data/test/schemas/extends_and_additionalProperties-2-ref.schema.json +33 -0
  71. data/test/schemas/good_schema_1.json +10 -0
  72. data/test/schemas/good_schema_2.json +10 -0
  73. data/test/schemas/good_schema_extends1.json +10 -0
  74. data/test/schemas/good_schema_extends2.json +13 -0
  75. data/test/schemas/inner.schema.json +21 -0
  76. data/test/schemas/one_of_ref_links_schema.json +16 -0
  77. data/test/schemas/self_link_schema.json +17 -0
  78. data/test/schemas/up_link_schema.json +17 -0
  79. data/test/test_all_of_ref_schema.rb +11 -0
  80. data/test/test_any_of_ref_schema.rb +11 -0
  81. data/test/test_bad_schema_ref.rb +33 -0
  82. data/test/test_extended_schema.rb +68 -0
  83. data/test/test_extends_and_additionalProperties.rb +50 -0
  84. data/test/test_files_v3.rb +52 -0
  85. data/test/test_fragment_resolution.rb +31 -0
  86. data/test/test_full_validation.rb +209 -0
  87. data/test/test_jsonschema_draft1.rb +701 -0
  88. data/test/test_jsonschema_draft2.rb +773 -0
  89. data/test/test_jsonschema_draft3.rb +1236 -0
  90. data/test/test_jsonschema_draft4.rb +1356 -0
  91. data/test/test_model_validator.rb +52 -0
  92. data/test/test_one_of.rb +42 -0
  93. data/test/test_ruby_schema.rb +38 -0
  94. data/test/test_schema_type_attribute.rb +21 -0
  95. data/test/test_schema_validation.rb +85 -0
  96. metadata +180 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb6fcc088c202363c450dc1ed5eb833525e362d1
4
+ data.tar.gz: 271974d31cde79219d94907582e43c1b509a24b8
5
+ SHA512:
6
+ metadata.gz: 6f9781b9e7f86e20326fefe95660dada22dcba3b37d2da1f1b15b2deb4e5db295e8c509f3d87cee5172812c6229e5f19dc7692834aedf4d485b15cced5ceaacd
7
+ data.tar.gz: a80c9ea99cb10adf73d314d09dbd53a6e5e00b1d29986fe24002b8ab061e417fc76df12ca5288d51cf6a9292e330dbadd5d78d7096bb6f60246f6d7ac243becc
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010-2011, Lookingglass Cyber Solutions
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,354 @@
1
+ h1. Ruby JSON Schema Validator
2
+
3
+ This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04. Legacy support for "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03, "JSON Schema Draft 2":http://tools.ietf.org/html/draft-zyp-json-schema-02, and "JSON Schema Draft 1":http://tools.ietf.org/html/draft-zyp-json-schema-01 is also included.
4
+
5
+ h2. Version 2.0.0 Upgrade Notes
6
+
7
+ Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the <code>$schema</code> keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade.
8
+
9
+ h2. Dependencies
10
+
11
+ The JSON::Schema library has no dependencies if the validation methods are called using Ruby objects. However, either the <code>json</code> or the <code>yajl-ruby</code> gem needs to be installed to validate JSON strings or files containing JSON data.
12
+
13
+ h2. Installation
14
+
15
+ From rubygems.org:
16
+
17
+ <pre>
18
+ gem install json-schema
19
+ </pre>
20
+
21
+ From the git repo:
22
+
23
+ <pre>
24
+ $ gem build json-schema.gemspec
25
+ $ gem install json-schema-2.2.2.gem
26
+ </pre>
27
+
28
+
29
+ h2. Usage
30
+
31
+ Three base validation methods exist: <code>validate</code>, <code>validate!</code>, and <code>fully_validate</code>. The first returns a boolean on whether a validation attempt passes and the second will throw a <code>JSON::Schema::ValidationError</code> with an appropriate message/trace on where the validation failed. The third validation method does not immediately fail upon a validation error and instead builds an array of validation errors return when validation is complete.
32
+
33
+ All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to these methods is always the schema, the second is always the data to validate. An optional third options argument is also accepted; available options are used in the examples below.
34
+
35
+ By default, the validator uses the "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04 specification for validation; however, the user is free to specify additional specifications or extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is included by either passing an optional <code>:version</code> parameter to the <code>validate</code> method (set either as <code>:draft1</code> or <code>draft2</code>), or by declaring the <code>$schema</code> attribute in the schema and referencing the appropriate specification URI. Note that the <code>$schema</code> attribute takes precedence over the <code>:version</code> option during parsing and validation.
36
+
37
+ h3. Validate Ruby objects against a Ruby schema
38
+
39
+ <pre>
40
+ require 'rubygems'
41
+ require 'json-schema'
42
+
43
+ schema = {
44
+ "type" => "object",
45
+ "required" => ["a"],
46
+ "properties" => {
47
+ "a" => {"type" => "integer"}
48
+ }
49
+ }
50
+
51
+ data = {
52
+ "a" => 5
53
+ }
54
+
55
+ JSON::Validator.validate(schema, data)
56
+ </pre>
57
+
58
+ h3. Validate a JSON string against a JSON schema file
59
+
60
+ <pre>
61
+ require 'rubygems'
62
+ require 'json-schema'
63
+
64
+ JSON::Validator.validate('schema.json', '{"a" : 5}')
65
+ </pre>
66
+
67
+ h3. Validate a list of objects against a schema that represents the individual objects
68
+
69
+ <pre>
70
+ require 'rubygems'
71
+ require 'json-schema'
72
+
73
+ data = ['user','user','user']
74
+ JSON::Validator.validate('user.json', data, :list => true)
75
+ </pre>
76
+
77
+ h3. Strictly validate an object's properties
78
+
79
+ With the <code>:strict</code>code> option, validation fails when an object contains properties that are not defined in the schema's property list or doesn't match the <code>additionalProperties</code> property. Furthermore, all properties are treated as <code>required</code> by default.
80
+
81
+ <pre>
82
+ require 'rubygems'
83
+ require 'json-schema'
84
+
85
+ schema = {
86
+ "type" => "object",
87
+ "properties" => {
88
+ "a" => {"type" => "integer"},
89
+ "b" => {"type" => "integer"}
90
+ }
91
+ }
92
+
93
+ JSON::Validator.validate(schema, {"a" => 1, "b" => 2}, :strict => true) # ==> true
94
+ JSON::Validator.validate(schema, {"a" => 1, "b" => 2, "c" => 3}, :strict => true) # ==> false
95
+ JSON::Validator.validate(schema, {"a" => 1}, :strict => true) # ==> false
96
+ </pre>
97
+
98
+ h3. Catch a validation error and print it out
99
+
100
+ <pre>
101
+ require 'rubygems'
102
+ require 'json-schema'
103
+
104
+ schema = {
105
+ "type" => "object",
106
+ "required" => ["a"],
107
+ "properties" => {
108
+ "a" => {"type" => "integer"}
109
+ }
110
+ }
111
+
112
+ data = {
113
+ "a" => "taco"
114
+ }
115
+
116
+ begin
117
+ JSON::Validator.validate!(schema, data)
118
+ rescue JSON::Schema::ValidationError
119
+ puts $!.message
120
+ end
121
+ </pre>
122
+
123
+
124
+ h3. Fully validate against a schema and catch all errors
125
+
126
+ <pre>
127
+ require 'rubygems'
128
+ require 'json-schema'
129
+
130
+ schema = {
131
+ "type" => "object",
132
+ "required" => ["a","b"],
133
+ "properties" => {
134
+ "a" => {"type" => "integer"},
135
+ "b" => {"type" => "string"}
136
+ }
137
+ }
138
+
139
+ data = {
140
+ "a" => "taco"
141
+ }
142
+
143
+ errors = JSON::Validator.fully_validate(schema, data)
144
+
145
+ # ["The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", "The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#"]
146
+ </pre>
147
+
148
+ h3. Fully validate against a schema and catch all errors as objects
149
+
150
+ <pre>
151
+ require 'rubygems'
152
+ require 'json-schema'
153
+
154
+ schema = {
155
+ "type" => "object",
156
+ "required" => ["a","b"],
157
+ "properties" => {
158
+ "a" => {"type" => "integer"},
159
+ "b" => {"type" => "string"}
160
+ }
161
+ }
162
+
163
+ data = {
164
+ "a" => "taco"
165
+ }
166
+
167
+ errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)
168
+
169
+ # [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#<URI::Generic:0x103a76198 URL:03179a21-197e-5414-9611-e9f63e8324cd#>, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#<URI::Generic:0x103a76198 URL:03179a21-197e-5414-9611-e9f63e8324cd#>, :failed_attribute=>"Properties", :fragment=>"#/"}]
170
+
171
+ </pre>
172
+
173
+ h3. Validate against a fragment of a supplied schema
174
+
175
+ <pre>
176
+ require 'rubygems'
177
+ require 'json-schema'
178
+
179
+ schema = {
180
+ "type" => "object",
181
+ "required" => ["a","b"],
182
+ "properties" => {
183
+ "a" => {"type" => "integer"},
184
+ "b" => {"type" => "string"},
185
+ "c" => {
186
+ "type" => "object",
187
+ "properties" => {
188
+ "z" => {"type" => "integer"}
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ data = {
195
+ "z" => 1
196
+ }
197
+
198
+ JSON::Validator.validate(schema, data, :fragment => "#/properties/c")
199
+ </pre>
200
+
201
+ h3. Validate a JSON object against a JSON schema object, while also validating the schema itself
202
+
203
+ <pre>
204
+ require 'rubygems'
205
+ require 'json-schema'
206
+
207
+ schema = {
208
+ "type" => "object",
209
+ "required" => ["a"],
210
+ "properties" => {
211
+ "a" => {"type" => "integer"} # This will fail schema validation!
212
+ }
213
+ }
214
+
215
+ data = {
216
+ "a" => 5
217
+ }
218
+
219
+ JSON::Validator.validate(schema, data, :validate_schema => true)
220
+ </pre>
221
+
222
+ h3. Validate a JSON object against a JSON schema object, while inserting default values from the schema
223
+
224
+ With the :insert_defaults option set to true any missing property that has a
225
+ default value specified in the schema will be inserted into the validated data. The inserted default value is validated hence catching a schema that specifies an invalid default value.
226
+
227
+ <pre>
228
+ require 'rubygems'
229
+ require 'json-schema'
230
+
231
+ schema = {
232
+ "type" => "object",
233
+ "required" => ["a"],
234
+ "properties" => {
235
+ "a" => {"type" => "integer", "default" => 42},
236
+ "b" => {"type" => "integer"}
237
+ }
238
+ }
239
+
240
+ # Would not normally validate because "a" is missing and required by schema,
241
+ # but "default" option allows insertion of valid default.
242
+ data = {
243
+ "b" => 5
244
+ }
245
+
246
+ JSON::Validator.validate(schema, data)
247
+ # false
248
+
249
+ JSON::Validator.validate(schema, data, :insert_defaults => true)
250
+ # true
251
+ # data = {
252
+ # "a" => 42,
253
+ # "b" => 5
254
+ # }
255
+
256
+ </pre>
257
+ h3. Validate an object against a JSON Schema Draft 2 schema
258
+
259
+ <pre>
260
+ require 'rubygems'
261
+ require 'json-schema'
262
+
263
+ schema = {
264
+ "type" => "object",
265
+ "properties" => {
266
+ "a" => {"type" => "integer", "optional" => true}
267
+ }
268
+ }
269
+
270
+ data = {
271
+ "a" => 5
272
+ }
273
+
274
+ JSON::Validator.validate(schema, data, :version => :draft2)
275
+ </pre>
276
+
277
+
278
+ h3. Extend an existing schema and validate against it
279
+
280
+ For this example, we are going to extend the "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03 specification by adding a 'bitwise-and' property for validation.
281
+
282
+ <pre>
283
+ require 'rubygems'
284
+ require 'json-schema'
285
+
286
+ class BitwiseAndAttribute < JSON::Schema::Attribute
287
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
288
+ if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0
289
+ message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-or']}"
290
+ raise JSON::Schema::ValidationError.new(message, fragments, current_schema)
291
+ end
292
+ end
293
+ end
294
+
295
+ class ExtendedSchema < JSON::Schema::Validator
296
+ def initialize
297
+ super
298
+ extend_schema_definition("http://json-schema.org/draft-03/schema#")
299
+ @attributes["bitwise-and"] = BitwiseAndAttribute
300
+ @uri = URI.parse("http://test.com/test.json")
301
+ end
302
+
303
+ JSON::Validator.register_validator(self.new)
304
+ end
305
+
306
+ schema = {
307
+ "$schema" => "http://test.com/test.json",
308
+ "properties" => {
309
+ "a" => {
310
+ "bitwise-and" => 1
311
+ },
312
+ "b" => {
313
+ "type" => "string"
314
+ }
315
+ }
316
+ }
317
+
318
+ data = {
319
+ "a" => 0
320
+ }
321
+
322
+ data = {"a" => 1, "b" => "taco"}
323
+ JSON::Validator.validate(schema,data) # => true
324
+ data = {"a" => 1, "b" => 5}
325
+ JSON::Validator.validate(schema,data) # => false
326
+ data = {"a" => 0, "b" => "taco"}
327
+ JSON::Validator.validate(schema,data) # => false
328
+ </pre>
329
+
330
+ h2. JSON Backends
331
+
332
+ The JSON Schema library currently supports the <code>json</code> and <code>yajl-ruby</code> backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user.
333
+
334
+ If more than one of the supported JSON backends are installed, the <code>yajl-ruby</code> parser is used by default. This can be changed by issuing the following before validation:
335
+
336
+ <pre>
337
+ JSON::Validator.json_backend = :json
338
+ </pre>
339
+
340
+ Optionally, the JSON Schema library supports using the MultiJSON library for selecting JSON backends. If the MultiJSON library is installed, it will be autoloaded.
341
+
342
+ h2. Notes
343
+
344
+ The 'format' attribute is only validated for the following values:
345
+
346
+ * date-time
347
+ * date
348
+ * time
349
+ * ip-address
350
+ * ipv6
351
+
352
+ All other 'format' attribute values are simply checked to ensure the instance value is of the correct datatype (e.g., an instance value is validated to be an integer or a float in the case of 'utc-millisec').
353
+
354
+ Additionally, JSON::Validator does not handle any json hyperschema attributes.
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+
3
+ if begin
4
+ Gem::Specification::find_by_name('multi_json')
5
+ rescue Gem::LoadError
6
+ false
7
+ rescue
8
+ Gem.available?('multi_json')
9
+ end
10
+ require 'multi_json'
11
+
12
+ # Force MultiJson to load an engine before we define the JSON constant here; otherwise,
13
+ # it looks for things that are under the JSON namespace that aren't there (since we have defined it here)
14
+ MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
15
+ end
16
+
17
+ require 'rubygems'
18
+ require 'json-schema/util/hash'
19
+ require 'json-schema/util/array_set'
20
+ require 'json-schema/schema'
21
+ require 'json-schema/validator'
22
+ Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/*.rb")].each {|file| require file }
23
+ Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].sort!.each {|file| require file }
24
+ require 'json-schema/uri/file'
25
+ require 'json-schema/model_validator'
@@ -0,0 +1,23 @@
1
+ module JSON
2
+ class Schema
3
+ class AdditionalItemsAttribute < Attribute
4
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
5
+ if data.is_a?(Array) && current_schema.schema['items'].is_a?(Array)
6
+ if current_schema.schema['additionalItems'] == false && current_schema.schema['items'].length != data.length
7
+ message = "The property '#{build_fragment(fragments)}' contains additional array elements outside of the schema when none are allowed"
8
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors], { property: last_fragment_as_symbol(fragments), failure: :additional_items })
9
+ elsif current_schema.schema['additionalItems'].is_a?(Hash)
10
+ schema = JSON::Schema.new(current_schema.schema['additionalItems'],current_schema.uri,validator)
11
+ data.each_with_index do |item,i|
12
+ if i >= current_schema.schema['items'].length
13
+ fragments << i.to_s
14
+ schema.validate(item, fragments, processor, options)
15
+ fragments.pop
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,67 @@
1
+ require 'json-schema/attributes/extends'
2
+
3
+ module JSON
4
+ class Schema
5
+ class AdditionalPropertiesAttribute < Attribute
6
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
+ if data.is_a?(Hash) && (
8
+ current_schema.schema['type'].nil? || (
9
+ current_schema.schema['type'].is_a?(String) &&
10
+ current_schema.schema['type'].downcase == 'object'
11
+ )
12
+ )
13
+ extra_properties = data.keys
14
+ extra_properties = remove_valid_properties(extra_properties, current_schema, validator)
15
+
16
+ addprop = current_schema.schema['additionalProperties']
17
+ if addprop.is_a?(Hash)
18
+ matching_properties = extra_properties # & addprop.keys
19
+ matching_properties.each do |key|
20
+ schema = JSON::Schema.new(addprop[key] || addprop, current_schema.uri, validator)
21
+ fragments << key
22
+ schema.validate(data[key],fragments,processor,options)
23
+ fragments.pop
24
+ end
25
+ extra_properties -= matching_properties
26
+ end
27
+ if !extra_properties.empty? and (addprop == false or (addprop.is_a?(Hash) and !addprop.empty?))
28
+ message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
29
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors], { property: last_fragment_as_symbol(fragments), failure: :additional_properties })
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.remove_valid_properties(extra_properties, current_schema, validator)
35
+
36
+ if current_schema.schema['properties']
37
+ extra_properties = extra_properties - current_schema.schema['properties'].keys
38
+ end
39
+
40
+ if current_schema.schema['patternProperties']
41
+ current_schema.schema['patternProperties'].each_key do |key|
42
+ r = Regexp.new(key)
43
+ extras_clone = extra_properties.clone
44
+ extras_clone.each do |prop|
45
+ if r.match(prop)
46
+ extra_properties = extra_properties - [prop]
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ if schemas= current_schema.schema['extends']
53
+ schemas = [schemas] if !schemas.is_a?(Array)
54
+ schemas.each do |schema_value|
55
+ temp_uri,extended_schema= JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator)
56
+ if extended_schema
57
+ extra_properties= remove_valid_properties(extra_properties, extended_schema, validator)
58
+ end
59
+ end
60
+ end
61
+
62
+ extra_properties
63
+ end
64
+
65
+ end
66
+ end
67
+ end