sk-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,434 @@
1
+ # vim: fileencoding=utf-8
2
+
3
+ module JSON
4
+ class Schema
5
+ VERSION = '1.0.0'
6
+ class ValueError < Exception;end
7
+ TypesMap = {
8
+ "string" => String,
9
+ "integer" => Integer,
10
+ "number" => [Integer, Float],
11
+ "boolean" => [TrueClass, FalseClass],
12
+ "object" => Hash,
13
+ "array" => Array,
14
+ "null" => NilClass,
15
+ "any" => nil
16
+ }
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
48
+ @interactive = interactive
49
+ @refmap = {}
50
+ end
51
+
52
+ def validate data, schema
53
+ @refmap = {
54
+ '$' => schema
55
+ }
56
+ _validate(data, schema)
57
+ end
58
+
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 '$'"
64
+ end
65
+ @refmap[id] = schema
66
+ end
67
+ return x
68
+ end
69
+
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
+
81
+ if converted_fieldtype && fieldexists
82
+ # fld is optional, type is not nil, and field is nil
83
+ return x if val == nil && schema['optional'] && converted_fieldtype != NilClass
84
+ if converted_fieldtype.kind_of? Array
85
+ datavalid = false
86
+ converted_fieldtype.each do |type|
87
+ begin
88
+ validate_type(x, fieldname, type, type)
89
+ datavalid = true
90
+ break
91
+ rescue ValueError
92
+ next
93
+ end
94
+ end
95
+ unless datavalid
96
+ raise ValueError, "Value #{val} for field '#{fieldname}' is not of type #{fieldtype}"
97
+ end
98
+ elsif converted_fieldtype.kind_of? Hash
99
+ begin
100
+ __validate(fieldname, x, converted_fieldtype)
101
+ rescue ValueError => e
102
+ raise e
103
+ end
104
+ else
105
+ unless val.kind_of? converted_fieldtype
106
+ raise ValueError, "Value #{val} for field '#{fieldname}' is not of type #{fieldtype}"
107
+ end
108
+ end
109
+ end
110
+ return x
111
+ end
112
+
113
+ def validate_properties x, fieldname, schema, properties=nil
114
+ if !properties.nil? && x[fieldname]
115
+ value = x[fieldname]
116
+ if value
117
+ if value.kind_of? Hash
118
+ if properties.kind_of? Hash
119
+ properties.each do |key, val|
120
+ __validate(key, value, val)
121
+ end
122
+ else
123
+ raise ValueError, "Properties definition of field '#{fieldname}' is not an object"
124
+ end
125
+ end
126
+ end
127
+ end
128
+ return x
129
+ end
130
+
131
+ def validate_items x, fieldname, schema, items=nil
132
+ if !items.nil? && x[fieldname]
133
+ value = x[fieldname]
134
+ unless value.nil?
135
+ if value.kind_of? Array
136
+ if items.kind_of? Array
137
+ if items.size == value.size
138
+ items.each_with_index do |item, index|
139
+ begin
140
+ validate(value[index], item)
141
+ rescue ValueError => e
142
+ raise ValueError, "Failed to validate field '#{fieldname}' list schema: #{e.message}"
143
+ end
144
+ end
145
+ else
146
+ raise ValueError, "Length of list #{value} for field '#{fieldname}' is not equal to length of schema list"
147
+ end
148
+ elsif items.kind_of? Hash
149
+ value.each do |val|
150
+ begin
151
+ _validate(val, items)
152
+ rescue ValueError => e
153
+ raise ValueError, "Failed to validate field '#{fieldname}' list schema: #{e.message}"
154
+ end
155
+ end
156
+ else
157
+ raise ValueError, "Properties definition of field '#{fieldname}' is not a list or an object"
158
+ end
159
+ end
160
+ end
161
+ end
162
+ return x
163
+ end
164
+
165
+ def validate_optional x, fieldname, schema, optional=false
166
+ if !x.include?(fieldname) && !optional
167
+ raise ValueError, "Required field '#{fieldname}' is missing"
168
+ end
169
+ return x
170
+ end
171
+
172
+ def validate_additionalProperties x, fieldname, schema, additional_properties=nil
173
+ unless additional_properties.nil?
174
+ if additional_properties.kind_of? TrueClass
175
+ return x
176
+ end
177
+ value = x[fieldname]
178
+ if additional_properties.kind_of?(Hash) || additional_properties.kind_of?(FalseClass)
179
+ properties = schema["properties"]
180
+ unless properties
181
+ properties = {}
182
+ end
183
+ value.keys.each do |key|
184
+ unless properties.include? key
185
+ if additional_properties.kind_of? FalseClass
186
+ raise ValueError, "Additional properties not defined by 'properties' are not allowed in field '#{fieldname}'"
187
+ else
188
+ __validate(key, value, additional_properties)
189
+ end
190
+ end
191
+ end
192
+ else
193
+ raise ValueError, "additionalProperties schema definition for field '#{fieldname}' is not an object"
194
+ end
195
+ end
196
+ return x
197
+ end
198
+
199
+ def validate_requires x, fieldname, schema, requires=nil
200
+ if x[fieldname] && !requires.nil?
201
+ unless x[requires]
202
+ raise ValueError, "Field '#{requires}' is required by field '#{fieldname}'"
203
+ end
204
+ end
205
+ return x
206
+ end
207
+
208
+ def validate_identity x, fieldname, schema, unique=false
209
+ return x
210
+ end
211
+
212
+ def validate_minimum x, fieldname, schema, minimum=nil
213
+ if !minimum.nil? && x[fieldname]
214
+ value = x[fieldname]
215
+ if value
216
+ if (value.kind_of?(Integer) || value.kind_of?(Float)) && value < minimum
217
+ raise ValueError, "Value #{value} for field '#{fieldname}' is less than minimum value: #{minimum}"
218
+ elsif value.kind_of?(Array) && value.size < minimum
219
+ raise ValueError, "Value #{value} for field '#{fieldname}' has fewer values than the minimum: #{minimum}"
220
+ end
221
+ end
222
+ end
223
+ return x
224
+ end
225
+
226
+ def validate_maximum x, fieldname, schema, maximum=nil
227
+ if !maximum.nil? && x[fieldname]
228
+ value = x[fieldname]
229
+ if value
230
+ if (value.kind_of?(Integer) || value.kind_of?(Float)) && value > maximum
231
+ raise ValueError, "Value #{value} for field '#{fieldname}' is greater than maximum value: #{maximum}"
232
+ elsif value.kind_of?(Array) && value.size > maximum
233
+ raise ValueError, "Value #{value} for field '#{fieldname}' has more values than the maximum: #{maximum}"
234
+ end
235
+ end
236
+ end
237
+ return x
238
+ end
239
+
240
+ def validate_minItems x, fieldname, schema, minitems=nil
241
+ if !minitems.nil? && x[fieldname]
242
+ value = x[fieldname]
243
+ if value
244
+ if value.kind_of?(Array) && value.size < minitems
245
+ raise ValueError, "Value #{value} for field '#{fieldname}' must have a minimum of #{minitems} items"
246
+ end
247
+ end
248
+ end
249
+ return x
250
+ end
251
+
252
+ def validate_maxItems x, fieldname, schema, maxitems=nil
253
+ if !maxitems.nil? && x[fieldname]
254
+ value = x[fieldname]
255
+ if value
256
+ if value.kind_of?(Array) && value.size > maxitems
257
+ raise ValueError, "Value #{value} for field '#{fieldname}' must have a maximum of #{maxitems} items"
258
+ end
259
+ end
260
+ end
261
+ return x
262
+ end
263
+
264
+ def validate_pattern x, fieldname, schema, pattern=nil
265
+ value = x[fieldname]
266
+ if !pattern.nil? && value && value.kind_of?(String)
267
+ p = Regexp.new(pattern)
268
+ if !p.match(value)
269
+ raise ValueError, "Value #{value} for field '#{fieldname}' does not match regular expression '#{pattern}'"
270
+ end
271
+ end
272
+ return x
273
+ end
274
+
275
+ def validate_maxLength x, fieldname, schema, length=nil
276
+ value = x[fieldname]
277
+ if !length.nil? && value && value.kind_of?(String)
278
+ # string length => 正規表現で分割して計測
279
+ if value.split(//).size > length
280
+ raise ValueError, "Length of value #{value} for field '#{fieldname}' must be less than or equal to #{length}"
281
+ end
282
+ end
283
+ return x
284
+ end
285
+
286
+ def validate_minLength x, fieldname, schema, length=nil
287
+ value = x[fieldname]
288
+ if !length.nil? && value && value.kind_of?(String)
289
+ if value.split(//).size < length
290
+ raise ValueError, "Length of value #{value} for field '#{fieldname}' must be more than or equal to #{length}"
291
+ end
292
+ end
293
+ return x
294
+ end
295
+
296
+ def validate_enum x, fieldname, schema, options=nil
297
+ value = x[fieldname]
298
+ if !options.nil? && value
299
+ unless options.kind_of? Array
300
+ raise ValueError, "Enumeration #{options} for field '#{fieldname}' is not a list type"
301
+ end
302
+ unless options.include? value
303
+ raise ValueError, "Value #{value} for field '#{fieldname}' is not in the enumeration: #{options}"
304
+ end
305
+ end
306
+ return x
307
+ end
308
+
309
+ def validate_options x, fieldname, schema, options=nil
310
+ return x
311
+ end
312
+
313
+ def validate_readonly x, fieldname, schema, readonly=false
314
+ return x
315
+ end
316
+
317
+ def validate_title x, fieldname, schema, title=nil
318
+ if !title.nil? && !title.kind_of?(String)
319
+ raise ValueError, "The title for field '#{fieldname}' must be a string"
320
+ end
321
+ return x
322
+ end
323
+
324
+ def validate_description x, fieldname, schema, description=nil
325
+ if !description.nil? && !description.kind_of?(String)
326
+ raise ValueError, "The description for field '#{fieldname}' must be a string"
327
+ end
328
+ return x
329
+ end
330
+
331
+ def validate_format x, fieldname, schema, format=nil
332
+ return x
333
+ end
334
+
335
+ def validate_default x, fieldname, schema, default=nil
336
+ if @interactive && !x.include?(fieldname) && !default.nil?
337
+ unless schema["readonly"]
338
+ x[fieldname] = default
339
+ end
340
+ end
341
+ return x
342
+ end
343
+
344
+ def validate_transient x, fieldname, schema, transient=false
345
+ return x
346
+ end
347
+
348
+ def validate_maxDecimal x, fieldname, schema, maxdecimal=nil
349
+ value = x[fieldname]
350
+ if !maxdecimal.nil? && value
351
+ maxdecstring = value.to_s
352
+ index = maxdecstring.index('.')
353
+ if index && maxdecstring[(index+1)...maxdecstring.size].split(//u).size > maxdecimal
354
+ raise ValueError, "Value #{value} for field '#{fieldname}' must not have more than #{maxdecimal} decimal places"
355
+ end
356
+ end
357
+ return x
358
+ end
359
+
360
+ def validate_hidden x, fieldname, schema, hidden=false
361
+ return x
362
+ end
363
+
364
+ def validate_disallow x, fieldname, schema, disallow=nil
365
+ if !disallow.nil?
366
+ begin
367
+ validate_type(x, fieldname, schema, disallow)
368
+ rescue ValueError
369
+ return x
370
+ end
371
+ raise ValueError, "Value #{x[fieldname]} of type #{disallow} is disallowed for field '#{fieldname}'"
372
+ end
373
+ return x
374
+ end
375
+
376
+ def validate_extends x, fieldname, schema, extends=nil
377
+ return x
378
+ end
379
+
380
+ def convert_type fieldtype
381
+ if TypesList.include?(fieldtype) || fieldtype.kind_of?(Hash)
382
+ return fieldtype
383
+ elsif fieldtype.kind_of? Array
384
+ converted_fields = []
385
+ fieldtype.each do |subfieldtype|
386
+ converted_fields << convert_type(subfieldtype)
387
+ end
388
+ return converted_fields
389
+ elsif !fieldtype
390
+ return nil
391
+ else
392
+ fieldtype = fieldtype.to_s
393
+ if TypesMap.include?(fieldtype)
394
+ return TypesMap[fieldtype]
395
+ else
396
+ raise ValueError, "Field type '#{fieldtype}' is not supported."
397
+ end
398
+ end
399
+ end
400
+
401
+ def __validate fieldname, data, schema
402
+ if schema
403
+ if !schema.kind_of?(Hash)
404
+ raise ValueError, "Schema structure is invalid"
405
+ end
406
+ # copy
407
+ new_schema = Marshal.load(Marshal.dump(schema))
408
+ DefaultSchema.each do |key, val|
409
+ new_schema[key] = val unless new_schema.include?(key)
410
+ end
411
+ new_schema.each do |key ,val|
412
+ validatorname = "validate_"+key
413
+ begin
414
+ __send__(validatorname, data, fieldname, schema, new_schema[key])
415
+ rescue NoMethodError => e
416
+ raise ValueError, "Schema property '#{e.message}' is not supported"
417
+ end
418
+ end
419
+ end
420
+ return data
421
+ end
422
+
423
+ def _validate data, schema
424
+ __validate("_data", {"_data" => data}, schema)
425
+ end
426
+
427
+ class << self
428
+ def validate data, schema, interactive=true
429
+ validator = JSON::Schema.new(interactive)
430
+ validator.validate(data, schema)
431
+ end
432
+ end
433
+ end
434
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{jsonschema}
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Constellation"]
9
+ s.date = %q{2009-09-13}
10
+ s.description = %q{json schema library ruby porting from http://code.google.com/p/jsonschema/}
11
+ s.email = %q{utatane.tea@gmail.com}
12
+ s.extra_rdoc_files = ["README.rdoc"]
13
+ s.files = ["README.rdoc", "Rakefile", "test/jsonschema_test.rb", "lib/jsonschema.rb"]
14
+ s.homepage = %q{http://github.com/Constellation/jsonschema/tree/master}
15
+ s.rdoc_options = ["--main", "README.rdoc", "--charset", "utf-8", "--line-numbers", "--inline-source"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{jsonschema}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{json schema library ruby porting from http://code.google.com/p/jsonschema/}
20
+ s.test_files = ["test/jsonschema_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end