jsonschema 1.0.0 → 2.0.0

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.
Files changed (3) hide show
  1. data/lib/jsonschema.rb +206 -335
  2. data/test/jsonschema_test.rb +204 -7
  3. metadata +17 -5
data/lib/jsonschema.rb CHANGED
@@ -2,376 +2,260 @@
2
2
 
3
3
  module JSON
4
4
  class Schema
5
- VERSION = '1.0.0'
5
+ VERSION = '2.0.0'
6
6
  class ValueError < Exception;end
7
+ class Undefined;end
7
8
  TypesMap = {
8
9
  "string" => String,
9
- "integer" => Integer,
10
- "number" => [Integer, Float],
10
+ "integer" => [Integer, Fixnum],
11
+ "number" => [Integer, Float, Fixnum, Numeric],
11
12
  "boolean" => [TrueClass, FalseClass],
12
13
  "object" => Hash,
13
14
  "array" => Array,
14
15
  "null" => NilClass,
15
16
  "any" => nil
16
17
  }
17
- TypesList = [String, Integer, Float, TrueClass, FalseClass, Hash, Array, NilClass]
18
- DefaultSchema = {
19
- "id" => nil,
20
- "type" => nil,
21
- "properties" => nil,
22
- "items" => nil,
23
- "optional" => false,
24
- "additionalProperties" => nil,
25
- "requires" => nil,
26
- "identity" => nil,
27
- "minimum" => nil,
28
- "maximum" => nil,
29
- "minItems" => nil,
30
- "maxItems" => nil,
31
- "pattern" => nil,
32
- "maxLength" => nil,
33
- "minLength" => nil,
34
- "enum" => nil,
35
- "options" => nil,
36
- "readonly" => nil,
37
- "title" => nil,
38
- "description" => nil,
39
- "format" => nil,
40
- "default" => nil,
41
- "transient" => nil,
42
- "maxDecimal" => nil,
43
- "hidden" => nil,
44
- "disallow" => nil,
45
- "extends" => nil
46
- }
47
- def initialize interactive=true
18
+ TypesList = [String, Integer, Float, Fixnum, Numeric, TrueClass, FalseClass, Hash, Array, NilClass]
19
+ def initialize interactive
48
20
  @interactive = interactive
49
21
  @refmap = {}
50
22
  end
51
23
 
52
- def validate data, schema
53
- @refmap = {
54
- '$' => schema
55
- }
56
- _validate(data, schema)
57
- end
24
+ def check_property value, schema, key, parent
25
+ if schema
26
+ # if @interactive && schema['readonly']
27
+ # raise ValueError, "#{key} is a readonly field , it can not be changed"
28
+ # end
58
29
 
59
- private
60
- def validate_id x, fieldname, schema, id=nil
61
- unless id.nil?
62
- if id == '$'
63
- raise ValueError, "Reference id for field '#{fieldname}' cannot equal '$'"
30
+ if schema['id']
31
+ @refmap[schema['id']] = schema
64
32
  end
65
- @refmap[id] = schema
66
- end
67
- return x
68
- end
69
33
 
70
- def validate_type x, fieldname, schema, fieldtype=nil
71
- converted_fieldtype = convert_type(fieldtype)
72
- fieldexists = true
73
- begin
74
- val = x.fetch(fieldname)
75
- rescue IndexError
76
- fieldexists = false
77
- ensure
78
- val = x[fieldname]
79
- end
80
- if converted_fieldtype && fieldexists
81
- if converted_fieldtype.kind_of? Array
82
- datavalid = false
83
- converted_fieldtype.each do |type|
84
- begin
85
- validate_type(x, fieldname, type, type)
86
- datavalid = true
87
- break
88
- rescue ValueError
89
- next
90
- end
91
- end
92
- unless datavalid
93
- raise ValueError, "Value #{val} for field '#{fieldname}' is not of type #{fieldtype}"
34
+ if schema['extends']
35
+ check_property(value, schema['extends'], key, parent)
36
+ end
37
+
38
+ if value == Undefined
39
+ unless schema['optional']
40
+ raise ValueError, "#{key} is missing and it is not optional"
94
41
  end
95
- elsif converted_fieldtype.kind_of? Hash
96
- begin
97
- __validate(fieldname, x, converted_fieldtype)
98
- rescue ValueError => e
99
- raise e
42
+
43
+ # default
44
+ if @interactive && !parent.include?(key) && !schema['default'].nil?
45
+ unless schema["readonly"]
46
+ parent[key] = schema['default']
47
+ end
100
48
  end
101
49
  else
102
- unless val.kind_of? converted_fieldtype
103
- raise ValueError, "Value #{val} for field '#{fieldname}' is not of type #{fieldtype}"
50
+
51
+ # type
52
+ if schema['type']
53
+ check_type(value, schema['type'], key, parent)
104
54
  end
105
- end
106
- end
107
- return x
108
- end
109
55
 
110
- def validate_properties x, fieldname, schema, properties=nil
111
- if !properties.nil? && x[fieldname]
112
- value = x[fieldname]
113
- if value
114
- if value.kind_of? Hash
115
- if properties.kind_of? Hash
116
- properties.each do |key, val|
117
- __validate(key, value, val)
118
- end
119
- else
120
- raise ValueError, "Properties definition of field '#{fieldname}' is not an object"
56
+ # disallow
57
+ if schema['disallow']
58
+ flag = true
59
+ begin
60
+ check_type(value, schema['disallow'], key, parent)
61
+ rescue ValueError
62
+ flag = false
121
63
  end
64
+ raise ValueError, "disallowed value was matched" if flag
122
65
  end
123
- end
124
- end
125
- return x
126
- end
127
66
 
128
- def validate_items x, fieldname, schema, items=nil
129
- if !items.nil? && x[fieldname]
130
- value = x[fieldname]
131
- unless value.nil?
132
- if value.kind_of? Array
133
- if items.kind_of? Array
134
- if items.size == value.size
135
- items.each_with_index do |item, index|
136
- begin
137
- validate(value[index], item)
138
- rescue ValueError => e
139
- raise ValueError, "Failed to validate field '#{fieldname}' list schema: #{e.message}"
67
+ unless value.nil?
68
+ if value.instance_of? Array
69
+ if schema['items']
70
+ if schema['items'].instance_of?(Array)
71
+ schema['items'].each_with_index {|val, index|
72
+ check_property(undefined_check(value, index), schema['items'][index], index, value)
73
+ }
74
+ if schema.include?('additionalProperties')
75
+ additional = schema['additionalProperties']
76
+ if additional.instance_of?(FalseClass)
77
+ if schema['items'].size < value.size
78
+ raise ValueError, "There are more values in the array than are allowed by the items and additionalProperties restrictions."
79
+ end
80
+ else
81
+ value.each_with_index {|val, index|
82
+ check_property(undefined_check(value, index), schema['additionalProperties'], index, value)
83
+ }
84
+ end
140
85
  end
86
+ else
87
+ value.each_with_index {|val, index|
88
+ check_property(undefined_check(value, index), schema['items'], index, value)
89
+ }
141
90
  end
142
- else
143
- raise ValueError, "Length of list #{value} for field '#{fieldname}' is not equal to length of schema list"
144
91
  end
145
- elsif items.kind_of? Hash
146
- value.each do |val|
147
- begin
148
- _validate(val, items)
149
- rescue ValueError => e
150
- raise ValueError, "Failed to validate field '#{fieldname}' list schema: #{e.message}"
92
+ if schema['minItems'] && value.size < schema['minItems']
93
+ raise ValueError, "There must be a minimum of #{schema['minItems']} in the array"
94
+ end
95
+ if schema['maxItems'] && value.size > schema['maxItems']
96
+ raise ValueError, "There must be a maximum of #{schema['maxItems']} in the array"
97
+ end
98
+ elsif schema['properties']
99
+ check_object(value, schema['properties'], schema['additionalProperties'])
100
+ elsif schema.include?('additionalProperties')
101
+ additional = schema['additionalProperties']
102
+ unless additional.instance_of?(TrueClass)
103
+ if additional.instance_of?(Hash) || additional.instance_of?(FalseClass)
104
+ properties = {}
105
+ value.each {|k, val|
106
+ if additional.instance_of?(FalseClass)
107
+ raise ValueError, "Additional properties not defined by 'properties' are not allowed in field '#{k}'"
108
+ else
109
+ check_property(val, schema['additionalProperties'], k, value)
110
+ end
111
+ }
112
+ else
113
+ raise ValueError, "additionalProperties schema definition for field '#{}' is not an object"
151
114
  end
152
115
  end
153
- else
154
- raise ValueError, "Properties definition of field '#{fieldname}' is not a list or an object"
155
116
  end
156
- end
157
- end
158
- end
159
- return x
160
- end
161
117
 
162
- def validate_optional x, fieldname, schema, optional=false
163
- if !x.include?(fieldname) && !optional
164
- raise ValueError, "Required field '#{fieldname}' is missing"
165
- end
166
- return x
167
- end
118
+ if value.instance_of?(String)
119
+ # pattern
120
+ if schema['pattern'] && !(value =~ Regexp.new(schema['pattern']))
121
+ raise ValueError, "does not match the regex pattern #{schema['pattern']}"
122
+ end
168
123
 
169
- def validate_additionalProperties x, fieldname, schema, additional_properties=nil
170
- unless additional_properties.nil?
171
- if additional_properties.kind_of? TrueClass
172
- return x
173
- end
174
- value = x[fieldname]
175
- if additional_properties.kind_of?(Hash) || additional_properties.kind_of?(FalseClass)
176
- properties = schema["properties"]
177
- unless properties
178
- properties = {}
179
- end
180
- value.keys.each do |key|
181
- unless properties.include? key
182
- if additional_properties.kind_of? FalseClass
183
- raise ValueError, "Additional properties not defined by 'properties' are not allowed in field '#{fieldname}'"
184
- else
185
- __validate(key, value, additional_properties)
124
+ strlen = value.split(//).size
125
+ # maxLength
126
+ if schema['maxLength'] && strlen > schema['maxLength']
127
+ raise ValueError, "may only be #{schema['maxLength']} characters long"
128
+ end
129
+
130
+ # minLength
131
+ if schema['minLength'] && strlen < schema['minLength']
132
+ raise ValueError, "must be at least #{schema['minLength']} characters long"
186
133
  end
187
134
  end
188
- end
189
- else
190
- raise ValueError, "additionalProperties schema definition for field '#{fieldname}' is not an object"
191
- end
192
- end
193
- return x
194
- end
195
135
 
196
- def validate_requires x, fieldname, schema, requires=nil
197
- if x[fieldname] && !requires.nil?
198
- unless x[requires]
199
- raise ValueError, "Field '#{requires}' is required by field '#{fieldname}'"
200
- end
201
- end
202
- return x
203
- end
136
+ if value.kind_of?(Numeric)
204
137
 
205
- def validate_identity x, fieldname, schema, unique=false
206
- return x
207
- end
138
+ # minimum + minimumCanEqual
139
+ if schema['minimum']
140
+ minimumCanEqual = schema.fetch('minimumCanEqual', Undefined)
141
+ if minimumCanEqual == Undefined || minimumCanEqual
142
+ if value < schema['minimum']
143
+ raise ValueError, "must have a minimum value of #{schema['minimum']}"
144
+ end
145
+ else
146
+ if value <= schema['minimum']
147
+ raise ValueError, "must have a minimum value of #{schema['minimum']}"
148
+ end
149
+ end
150
+ end
208
151
 
209
- def validate_minimum x, fieldname, schema, minimum=nil
210
- if !minimum.nil? && x[fieldname]
211
- value = x[fieldname]
212
- if value
213
- if (value.kind_of?(Integer) || value.kind_of?(Float)) && value < minimum
214
- raise ValueError, "Value #{value} for field '#{fieldname}' is less than minimum value: #{minimum}"
215
- elsif value.kind_of?(Array) && value.size < minimum
216
- raise ValueError, "Value #{value} for field '#{fieldname}' has fewer values than the minimum: #{minimum}"
217
- end
218
- end
219
- end
220
- return x
221
- end
152
+ # maximum + maximumCanEqual
153
+ if schema['maximum']
154
+ maximumCanEqual = schema.fetch('maximumCanEqual', Undefined)
155
+ if maximumCanEqual == Undefined || maximumCanEqual
156
+ if value > schema['maximum']
157
+ raise ValueError, "must have a maximum value of #{schema['maximum']}"
158
+ end
159
+ else
160
+ if value >= schema['maximum']
161
+ raise ValueError, "must have a maximum value of #{schema['maximum']}"
162
+ end
163
+ end
164
+ end
222
165
 
223
- def validate_maximum x, fieldname, schema, maximum=nil
224
- if !maximum.nil? && x[fieldname]
225
- value = x[fieldname]
226
- if value
227
- if (value.kind_of?(Integer) || value.kind_of?(Float)) && value > maximum
228
- raise ValueError, "Value #{value} for field '#{fieldname}' is greater than maximum value: #{maximum}"
229
- elsif value.kind_of?(Array) && value.size > maximum
230
- raise ValueError, "Value #{value} for field '#{fieldname}' has more values than the maximum: #{maximum}"
231
- end
232
- end
233
- end
234
- return x
235
- end
166
+ # maxDecimal
167
+ if schema['maxDecimal'] && schema['maxDecimal'].kind_of?(Numeric)
168
+ if value.to_s =~ /\.\d{#{schema['maxDecimal']+1},}/
169
+ raise ValueError, "may only have #{schema['maxDecimal']} digits of decimal places"
170
+ end
171
+ end
236
172
 
237
- def validate_minItems x, fieldname, schema, minitems=nil
238
- if !minitems.nil? && x[fieldname]
239
- value = x[fieldname]
240
- if value
241
- if value.kind_of?(Array) && value.size < minitems
242
- raise ValueError, "Value #{value} for field '#{fieldname}' must have a minimum of #{minitems} items"
243
- end
244
- end
245
- end
246
- return x
247
- end
173
+ end
248
174
 
249
- def validate_maxItems x, fieldname, schema, maxitems=nil
250
- if !maxitems.nil? && x[fieldname]
251
- value = x[fieldname]
252
- if value
253
- if value.kind_of?(Array) && value.size > maxitems
254
- raise ValueError, "Value #{value} for field '#{fieldname}' must have a maximum of #{maxitems} items"
255
- end
256
- end
257
- end
258
- return x
259
- end
175
+ # enum
176
+ if schema['enum']
177
+ unless(schema['enum'].detect{|enum| enum == value })
178
+ raise ValueError, "does not have a value in the enumeration #{schema['enum'].join(", ")}"
179
+ end
180
+ end
260
181
 
261
- def validate_pattern x, fieldname, schema, pattern=nil
262
- value = x[fieldname]
263
- if !pattern.nil? && value && value.kind_of?(String)
264
- p = Regexp.new(pattern)
265
- if !p.match(value)
266
- raise ValueError, "Value #{value} for field '#{fieldname}' does not match regular expression '#{pattern}'"
267
- end
268
- end
269
- return x
270
- end
182
+ # description
183
+ if schema['description'] && !schema['description'].instance_of?(String)
184
+ raise ValueError, "The description for field '#{value}' must be a string"
185
+ end
271
186
 
272
- def validate_maxLength x, fieldname, schema, length=nil
273
- value = x[fieldname]
274
- if !length.nil? && value && value.kind_of?(String)
275
- # string length => 正規表現で分割して計測
276
- if value.split(//).size > length
277
- raise ValueError, "Length of value #{value} for field '#{fieldname}' must be less than or equal to #{length}"
278
- end
279
- end
280
- return x
281
- end
187
+ # title
188
+ if schema['title'] && !schema['title'].instance_of?(String)
189
+ raise ValueError, "The title for field '#{value}' must be a string"
190
+ end
282
191
 
283
- def validate_minLength x, fieldname, schema, length=nil
284
- value = x[fieldname]
285
- if !length.nil? && value && value.kind_of?(String)
286
- if value.split(//).size < length
287
- raise ValueError, "Length of value #{value} for field '#{fieldname}' must be more than or equal to #{length}"
288
- end
289
- end
290
- return x
291
- end
192
+ # format
193
+ if schema['format']
194
+ end
292
195
 
293
- def validate_enum x, fieldname, schema, options=nil
294
- value = x[fieldname]
295
- if !options.nil? && value
296
- unless options.kind_of? Array
297
- raise ValueError, "Enumeration #{options} for field '#{fieldname}' is not a list type"
298
- end
299
- unless options.include? value
300
- raise ValueError, "Value #{value} for field '#{fieldname}' is not in the enumeration: #{options}"
196
+ end
301
197
  end
302
198
  end
303
- return x
304
199
  end
305
200
 
306
- def validate_options x, fieldname, schema, options=nil
307
- return x
308
- end
309
-
310
- def validate_readonly x, fieldname, schema, readonly=false
311
- return x
312
- end
313
-
314
- def validate_title x, fieldname, schema, title=nil
315
- if !title.nil? && !title.kind_of?(String)
316
- raise ValueError, "The title for field '#{fieldname}' must be a string"
317
- end
318
- return x
319
- end
201
+ def check_object value, object_type_def, additional
202
+ if object_type_def.instance_of? Hash
203
+ if !value.instance_of?(Hash) || value.instance_of?(Array)
204
+ raise ValueError, "an object is required"
205
+ end
320
206
 
321
- def validate_description x, fieldname, schema, description=nil
322
- if !description.nil? && !description.kind_of?(String)
323
- raise ValueError, "The description for field '#{fieldname}' must be a string"
207
+ object_type_def.each {|key, odef|
208
+ if key.index('__') != 0
209
+ check_property(undefined_check(value, key), odef, key, value)
210
+ end
211
+ }
324
212
  end
325
- return x
326
- end
327
-
328
- def validate_format x, fieldname, schema, format=nil
329
- return x
330
- end
331
-
332
- def validate_default x, fieldname, schema, default=nil
333
- if @interactive && !x.include?(fieldname) && !default.nil?
334
- unless schema["readonly"]
335
- x[fieldname] = default
213
+ value.each {|key, val|
214
+ if key.index('__') != 0 && object_type_def && !object_type_def[key] && additional == false
215
+ raise ValueError, "#{value.class} The property #{key} is not defined in the schema and the schema does not allow additional properties"
336
216
  end
337
- end
338
- return x
339
- end
340
-
341
- def validate_transient x, fieldname, schema, transient=false
342
- return x
343
- end
344
-
345
- def validate_maxDecimal x, fieldname, schema, maxdecimal=nil
346
- value = x[fieldname]
347
- if !maxdecimal.nil? && value
348
- maxdecstring = value.to_s
349
- index = maxdecstring.index('.')
350
- if index && maxdecstring[(index+1)...maxdecstring.size].split(//u).size > maxdecimal
351
- raise ValueError, "Value #{value} for field '#{fieldname}' must not have more than #{maxdecimal} decimal places"
217
+ requires = object_type_def && object_type_def[key] && object_type_def[key]['requires']
218
+ if requires && !value.include?(requires)
219
+ raise ValueError, "the presence of the property #{key} requires that #{requires} also be present"
352
220
  end
353
- end
354
- return x
355
- end
356
-
357
- def validate_hidden x, fieldname, schema, hidden=false
358
- return x
221
+ if object_type_def && object_type_def.instance_of?(Hash) && !object_type_def.include?(key)
222
+ check_property(val, additional, key, value)
223
+ end
224
+ if !@interactive && val && val['$schema']
225
+ check_property(val, val['$schema'], key, value)
226
+ end
227
+ }
359
228
  end
360
229
 
361
- def validate_disallow x, fieldname, schema, disallow=nil
362
- if !disallow.nil?
363
- begin
364
- validate_type(x, fieldname, schema, disallow)
365
- rescue ValueError
366
- return x
230
+ def check_type value, type, key, parent
231
+ converted_fieldtype = convert_type(type)
232
+ if converted_fieldtype
233
+ if converted_fieldtype.instance_of? Array
234
+ datavalid = false
235
+ converted_fieldtype.each do |t|
236
+ begin
237
+ check_type(value, t, key, parent)
238
+ datavalid = true
239
+ break
240
+ rescue ValueError
241
+ next
242
+ end
243
+ end
244
+ unless datavalid
245
+ raise ValueError, "#{value.class} value found, but a #{type} is required"
246
+ end
247
+ elsif converted_fieldtype.instance_of? Hash
248
+ check_property(value, type, key, parent)
249
+ else
250
+ unless value.instance_of? converted_fieldtype
251
+ raise ValueError, "#{value.class} value found, but a #{type} is required"
252
+ end
367
253
  end
368
- raise ValueError, "Value #{x[fieldname]} of type #{disallow} is disallowed for field '#{fieldname}'"
369
254
  end
370
- return x
371
255
  end
372
256
 
373
- def validate_extends x, fieldname, schema, extends=nil
374
- return x
257
+ def undefined_check value, key
258
+ value.fetch(key, Undefined)
375
259
  end
376
260
 
377
261
  def convert_type fieldtype
@@ -395,34 +279,21 @@ module JSON
395
279
  end
396
280
  end
397
281
 
398
- def __validate fieldname, data, schema
282
+ def validate instance, schema
283
+ @tree = {
284
+ 'self' => instance
285
+ }
399
286
  if schema
400
- if !schema.kind_of?(Hash)
401
- raise ValueError, "Schema structure is invalid"
402
- end
403
- # copy
404
- new_schema = Marshal.load(Marshal.dump(schema))
405
- DefaultSchema.each do |key, val|
406
- new_schema[key] = val unless new_schema.include?(key)
407
- end
408
- new_schema.each do |key ,val|
409
- validatorname = "validate_"+key
410
- begin
411
- __send__(validatorname, data, fieldname, schema, new_schema[key])
412
- rescue NoMethodError => e
413
- raise ValueError, "Schema property '#{e.message}' is not supported"
414
- end
415
- end
287
+ check_property(instance, schema, 'self', @tree)
288
+ elsif instance && instance['$schema']
289
+ # self definition schema
290
+ check_property(instance, instance['$schema'], 'self', @tree)
416
291
  end
417
- return data
418
- end
419
-
420
- def _validate data, schema
421
- __validate("_data", {"_data" => data}, schema)
292
+ return @tree['self']
422
293
  end
423
294
 
424
295
  class << self
425
- def validate data, schema, interactive=true
296
+ def validate data, schema=nil, interactive=true
426
297
  validator = JSON::Schema.new(interactive)
427
298
  validator.validate(data, schema)
428
299
  end
@@ -1,9 +1,72 @@
1
1
  require 'test/unit'
2
+ require 'open-uri'
3
+ require 'pp'
2
4
  require File.dirname(__FILE__) + '/../lib/jsonschema'
3
5
 
4
6
  class JSONSchemaTest < Test::Unit::TestCase
7
+ def test_self_schema
8
+ data1 = {
9
+ "$schema"=> {
10
+ "properties"=> {
11
+ "name"=> {
12
+ "type"=> "string"
13
+ },
14
+ "age" => {
15
+ "type"=> "integer",
16
+ "maximum"=> 125,
17
+ "optional"=> true
18
+ }
19
+ }
20
+ },
21
+ "name" => "John Doe",
22
+ "age" => 30,
23
+ "type" => "object"
24
+ }
25
+ assert_nothing_raised{
26
+ JSON::Schema.validate(data1)
27
+ }
28
+ data2 = {
29
+ "$schema"=> {
30
+ "properties"=> {
31
+ "name"=> {
32
+ "type"=> "integer"
33
+ },
34
+ "age" => {
35
+ "type"=> "integer",
36
+ "maximum"=> 125,
37
+ "optional"=> true
38
+ }
39
+ }
40
+ },
41
+ "name" => "John Doe",
42
+ "age" => 30,
43
+ "type" => "object"
44
+ }
45
+ assert_raise(JSON::Schema::ValueError){
46
+ JSON::Schema.validate(data2)
47
+ }
48
+ data3 = {
49
+ "$schema"=> {
50
+ "properties"=> {
51
+ "name"=> {
52
+ "type"=> "integer"
53
+ },
54
+ "age" => {
55
+ "type"=> "integer",
56
+ "maximum"=> 125,
57
+ "optional"=> true
58
+ }
59
+ }
60
+ },
61
+ "name" => "John Doe",
62
+ }
63
+ assert_raise(JSON::Schema::ValueError){
64
+ JSON::Schema.validate(data3)
65
+ }
66
+ end
67
+
5
68
  def test_maximum
6
- schema = {
69
+ schema1 = {
7
70
  "type" => "object",
8
71
  "properties" => {
9
72
  "prop01" => {
@@ -32,6 +95,91 @@ class JSONSchemaTest < Test::Unit::TestCase
32
95
  "prop01"=> 9,
33
96
  "prop02"=> 21
34
97
  }
98
+ assert_nothing_raised{
99
+ JSON::Schema.validate(data1, schema1)
100
+ }
101
+ assert_nothing_raised{
102
+ JSON::Schema.validate(data2, schema1)
103
+ }
104
+ assert_raise(JSON::Schema::ValueError){
105
+ JSON::Schema.validate(data3, schema1)
106
+ }
107
+ assert_raise(JSON::Schema::ValueError){
108
+ JSON::Schema.validate(data4, schema1)
109
+ }
110
+ schema2 = {
111
+ "type" => "object",
112
+ "properties" => {
113
+ "prop01" => {
114
+ "type" => "number",
115
+ "maximum" => 10,
116
+ "maximumCanEqual" => true
117
+ },
118
+ "prop02" => {
119
+ "type" => "integer",
120
+ "maximum" => 20,
121
+ "maximumCanEqual" => false
122
+ }
123
+ }
124
+ }
125
+ data5 = {
126
+ "prop01"=> 10,
127
+ "prop02"=> 10
128
+ }
129
+ data6 = {
130
+ "prop01"=> 10,
131
+ "prop02"=> 19
132
+ }
133
+ data7 = {
134
+ "prop01"=> 11,
135
+ "prop02"=> 19
136
+ }
137
+ data8 = {
138
+ "prop01"=> 9,
139
+ "prop02"=> 20
140
+ }
141
+ assert_nothing_raised{
142
+ JSON::Schema.validate(data5, schema2)
143
+ }
144
+ assert_nothing_raised{
145
+ JSON::Schema.validate(data6, schema2)
146
+ }
147
+ assert_raise(JSON::Schema::ValueError){
148
+ JSON::Schema.validate(data7, schema2)
149
+ }
150
+ assert_raise(JSON::Schema::ValueError){
151
+ JSON::Schema.validate(data8, schema2)
152
+ }
153
+ end
154
+
155
+ def test_extends
156
+ schema = {
157
+ "type" => "object",
158
+ "properties" => {
159
+ "prop01" => {
160
+ "type" => "number",
161
+ "minimum" => 10
162
+ },
163
+ "prop02" => {}
164
+ }
165
+ }
166
+ schema["properties"]["prop02"]["extends"] = schema["properties"]["prop01"]
167
+ data1 = {
168
+ "prop01"=> 21,
169
+ "prop02"=> 21
170
+ }
171
+ data2 = {
172
+ "prop01"=> 10,
173
+ "prop02"=> 20
174
+ }
175
+ data3 = {
176
+ "prop01"=> 9,
177
+ "prop02"=> 21
178
+ }
179
+ data4 = {
180
+ "prop01"=> 10,
181
+ "prop02"=> 9
182
+ }
35
183
  assert_nothing_raised{
36
184
  JSON::Schema.validate(data1, schema)
37
185
  }
@@ -47,9 +195,9 @@ class JSONSchemaTest < Test::Unit::TestCase
47
195
  end
48
196
 
49
197
  def test_minimum
50
- schema = {
198
+ schema1 = {
51
199
  "type" => "object",
52
- "properties" => {
200
+ "properties" => {
53
201
  "prop01" => {
54
202
  "type" => "number",
55
203
  "minimum" => 10
@@ -77,16 +225,52 @@ class JSONSchemaTest < Test::Unit::TestCase
77
225
  "prop02"=> 19
78
226
  }
79
227
  assert_nothing_raised{
80
- JSON::Schema.validate(data1, schema)
228
+ JSON::Schema.validate(data1, schema1)
81
229
  }
82
230
  assert_nothing_raised{
83
- JSON::Schema.validate(data2, schema)
231
+ JSON::Schema.validate(data2, schema1)
84
232
  }
85
233
  assert_raise(JSON::Schema::ValueError){
86
- JSON::Schema.validate(data3, schema)
234
+ JSON::Schema.validate(data3, schema1)
87
235
  }
88
236
  assert_raise(JSON::Schema::ValueError){
89
- JSON::Schema.validate(data4, schema)
237
+ JSON::Schema.validate(data4, schema1)
238
+ }
239
+ schema2 = {
240
+ "type" => "object",
241
+ "properties" => {
242
+ "prop01" => {
243
+ "type" => "number",
244
+ "minimum" => 10,
245
+ "minimumCanEqual" => false
246
+ },
247
+ "prop02" => {
248
+ "type" => "integer",
249
+ "minimum" => 19,
250
+ "minimumCanEqual" => true
251
+ }
252
+ }
253
+ }
254
+ data5 = {
255
+ "prop01"=> 11,
256
+ "prop02"=> 19
257
+ }
258
+ data6 = {
259
+ "prop01"=> 10,
260
+ "prop02"=> 19
261
+ }
262
+ data7 = {
263
+ "prop01"=> 11,
264
+ "prop02"=> 18
265
+ }
266
+ assert_nothing_raised{
267
+ JSON::Schema.validate(data5, schema2)
268
+ }
269
+ assert_raise(JSON::Schema::ValueError){
270
+ JSON::Schema.validate(data6, schema2)
271
+ }
272
+ assert_raise(JSON::Schema::ValueError){
273
+ JSON::Schema.validate(data7, schema2)
90
274
  }
91
275
  end
92
276
 
@@ -392,9 +576,22 @@ class JSONSchemaTest < Test::Unit::TestCase
392
576
  data2 = {
393
577
  "prop02"=>"blah"
394
578
  }
579
+ data3 = {
580
+ "prop01"=>"blah"
581
+ }
582
+ data4 = {
583
+ "prop01"=>"test",
584
+ "prop03"=>1,
585
+ }
395
586
  assert_raise(JSON::Schema::ValueError){
396
587
  JSON::Schema.validate(data2, schema)
397
588
  }
589
+ assert_raise(JSON::Schema::ValueError){
590
+ JSON::Schema.validate(data3, schema)
591
+ }
592
+ assert_raise(JSON::Schema::ValueError){
593
+ JSON::Schema.validate(data4, schema)
594
+ }
398
595
  end
399
596
 
400
597
  def test_default
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonschema
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 2
8
+ - 0
9
+ - 0
10
+ version: 2.0.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Constellation
@@ -9,7 +15,7 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-10-09 00:00:00 +09:00
18
+ date: 2010-08-23 00:00:00 +09:00
13
19
  default_executable:
14
20
  dependencies: []
15
21
 
@@ -41,21 +47,27 @@ rdoc_options:
41
47
  require_paths:
42
48
  - lib
43
49
  required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
44
51
  requirements:
45
52
  - - ">="
46
53
  - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
47
57
  version: "0"
48
- version:
49
58
  required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
50
60
  requirements:
51
61
  - - ">="
52
62
  - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
53
66
  version: "0"
54
- version:
55
67
  requirements: []
56
68
 
57
69
  rubyforge_project: jsonschema
58
- rubygems_version: 1.3.5
70
+ rubygems_version: 1.3.7
59
71
  signing_key:
60
72
  specification_version: 3
61
73
  summary: json schema library ruby porting from http://code.google.com/p/jsonschema/