jsonschema 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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/