json-schema 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -18,7 +18,7 @@ From the git repo:
18
18
 
19
19
  <pre>
20
20
  $ gem build json-schema.gemspec
21
- $ gem install json-schema-0.9.0.gem
21
+ $ gem install json-schema-0.9.1.gem
22
22
  </pre>
23
23
 
24
24
 
data/lib/json-schema.rb CHANGED
@@ -5,5 +5,4 @@ require 'schema'
5
5
  require 'validator'
6
6
  Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/*")].each {|file| require file }
7
7
  Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*")].each {|file| require file }
8
- require 'uri/file'
9
- require 'uri/uuid'
8
+ require 'uri/file'
@@ -3,8 +3,7 @@ module JSON
3
3
  class MaximumInclusiveAttribute < Attribute
4
4
  def self.validate(current_schema, data, fragments, validator, options = {})
5
5
  if data.is_a?(Numeric)
6
- current_schema.schema['maximumCanEqual'] = true if current_schema.schema['maximumCanEqual'].nil?
7
- if (current_schema.schema['maximumCanEqual'] ? data > current_schema.schema['maximum'] : data >= current_schema.schema['maximum'])
6
+ if (current_schema.schema['maximumCanEqual'] == false ? data >= current_schema.schema['maximum'] : data > current_schema.schema['maximum'])
8
7
  message = "The property '#{build_fragment(fragments)}' did not have a maximum value of #{current_schema.schema['maximum']}, "
9
8
  message += current_schema.schema['exclusiveMaximum'] ? 'exclusively' : 'inclusively'
10
9
  raise ValidationError.new(message, fragments, current_schema)
@@ -13,4 +12,4 @@ module JSON
13
12
  end
14
13
  end
15
14
  end
16
- end
15
+ end
@@ -3,8 +3,7 @@ module JSON
3
3
  class MinimumInclusiveAttribute < Attribute
4
4
  def self.validate(current_schema, data, fragments, validator, options = {})
5
5
  if data.is_a?(Numeric)
6
- current_schema.schema['minimumCanEqual'] = true if current_schema.schema['minimumCanEqual'].nil?
7
- if (current_schema.schema['minimumCanEqual'] ? data < current_schema.schema['minimum'] : data <= current_schema.schema['minimum'])
6
+ if (current_schema.schema['minimumCanEqual'] == false ? data <= current_schema.schema['minimum'] : data < current_schema.schema['minimum'])
8
7
  message = "The property '#{build_fragment(fragments)}' did not have a minimum value of #{current_schema.schema['minimum']}, "
9
8
  message += current_schema.schema['exclusiveMinimum'] ? 'exclusively' : 'inclusively'
10
9
  raise ValidationError.new(message, fragments, current_schema)
@@ -57,7 +57,7 @@ module JSON
57
57
 
58
58
  def validate(current_schema, data, fragments)
59
59
  current_schema.schema.each do |attr_name,attribute|
60
-
60
+
61
61
  if @attributes.has_key?(attr_name.to_s)
62
62
  @attributes[attr_name.to_s].validate(current_schema, data, fragments, self)
63
63
  end
@@ -83,7 +83,7 @@ module JSON
83
83
 
84
84
  def initialize(schema_data, data, opts={})
85
85
  @options = @@default_opts.clone.merge(opts)
86
-
86
+
87
87
  # I'm not a fan of this, but it's quick and dirty to get it working for now
88
88
  if @options[:version]
89
89
  @options[:version] = case @options[:version].to_s
@@ -302,12 +302,24 @@ module JSON
302
302
 
303
303
 
304
304
  private
305
-
305
+
306
+ if Gem.available?('uuidtools')
307
+ require 'uuidtools'
308
+ @@fake_uri_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
309
+ else
310
+ require 'uri/uuid'
311
+ @@fake_uri_generator = lambda{|s| UUID.create_v5(s,UUID::Nil).to_s }
312
+ end
313
+
314
+ def fake_uri schema
315
+ @@fake_uri_generator.call(schema)
316
+ end
317
+
306
318
  def initialize_schema(schema)
307
319
  if schema.is_a?(String)
308
320
  begin
309
321
  # Build a fake URI for this
310
- schema_uri = URI.parse(UUID.create_v5(schema,UUID::Nil).to_s)
322
+ schema_uri = URI.parse(fake_uri(schema))
311
323
  schema = JSON::Validator.parse(schema)
312
324
  if @options[:list]
313
325
  schema = {"type" => "array", "items" => schema}
@@ -340,7 +352,7 @@ module JSON
340
352
  if @options[:list]
341
353
  schema = {"type" => "array", "items" => schema}
342
354
  end
343
- schema_uri = URI.parse(UUID.create_v5(schema.inspect,UUID::Nil).to_s)
355
+ schema_uri = URI.parse(fake_uri(schema.inspect))
344
356
  schema = JSON::Schema.new(schema,schema_uri,@options[:version])
345
357
  Validator.add_schema(schema)
346
358
  else
@@ -0,0 +1,391 @@
1
+ require 'uri'
2
+ require 'open-uri'
3
+ require 'pathname'
4
+ require 'bigdecimal'
5
+ require 'digest/sha1'
6
+ require 'date'
7
+
8
+ module JSON
9
+
10
+ class Schema
11
+ class ValidationError < Exception
12
+ attr_reader :fragments, :schema
13
+
14
+ def initialize(message, fragments, schema)
15
+ @fragments = fragments
16
+ @schema = schema
17
+ message = "#{message} in schema #{schema.uri}"
18
+ super(message)
19
+ end
20
+ end
21
+
22
+ class SchemaError < Exception
23
+ end
24
+
25
+ class JsonParseError < Exception
26
+ end
27
+
28
+ class Attribute
29
+ def self.validate(current_schema, data, fragments, validator, options = {})
30
+ end
31
+
32
+ def self.build_fragment(fragments)
33
+ "#/#{fragments.join('/')}"
34
+ end
35
+ end
36
+
37
+ class Validator
38
+ attr_accessor :attributes, :uri
39
+
40
+ def initialize()
41
+ @attributes = {}
42
+ @uri = nil
43
+ end
44
+
45
+ def extend_schema_definition(schema_uri)
46
+ u = URI.parse(schema_uri)
47
+ validator = JSON::Validator.validators["#{u.scheme}://#{u.host}#{u.path}"]
48
+ if validator.nil?
49
+ raise SchemaError.new("Schema not found: #{u.scheme}://#{u.host}#{u.path}")
50
+ end
51
+ @attributes.merge!(validator.attributes)
52
+ end
53
+
54
+ def to_s
55
+ "#{@uri.scheme}://#{uri.host}#{uri.path}"
56
+ end
57
+
58
+ def validate(current_schema, data, fragments)
59
+ current_schema.schema.each do |attr_name,attribute|
60
+
61
+ if @attributes.has_key?(attr_name.to_s)
62
+ @attributes[attr_name.to_s].validate(current_schema, data, fragments, self)
63
+ end
64
+ end
65
+ data
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ class Validator
72
+
73
+ @@schemas = {}
74
+ @@cache_schemas = false
75
+ @@default_opts = {
76
+ :list => false,
77
+ :version => nil
78
+ }
79
+ @@validators = {}
80
+ @@default_validator = nil
81
+ @@available_json_backends = []
82
+ @@json_backend = nil
83
+
84
+ def initialize(schema_data, data, opts={})
85
+ @options = @@default_opts.clone.merge(opts)
86
+
87
+ # I'm not a fan of this, but it's quick and dirty to get it working for now
88
+ if @options[:version]
89
+ @options[:version] = case @options[:version].to_s
90
+ when "draft3"
91
+ "draft-03"
92
+ when "draft2"
93
+ "draft-02"
94
+ when "draft1"
95
+ "draft-01"
96
+ else
97
+ raise JSON::Schema::SchemaError.new("The requested JSON schema version is not supported")
98
+ end
99
+ u = URI.parse("http://json-schema.org/#{@options[:version]}/schema#")
100
+ validator = JSON::Validator.validators["#{u.scheme}://#{u.host}#{u.path}"]
101
+ @options[:version] = validator
102
+ end
103
+ @base_schema = initialize_schema(schema_data)
104
+ @data = initialize_data(data)
105
+ build_schemas(@base_schema)
106
+ end
107
+
108
+
109
+ # Run a simple true/false validation of data against a schema
110
+ def validate()
111
+ begin
112
+ @base_schema.validate(@data,[])
113
+ Validator.clear_cache
114
+ rescue JSON::Schema::ValidationError
115
+ Validator.clear_cache
116
+ raise $!
117
+ end
118
+ end
119
+
120
+
121
+ def load_ref_schema(parent_schema,ref)
122
+ uri = URI.parse(ref)
123
+ if uri.relative?
124
+ uri = parent_schema.uri.clone
125
+
126
+ # Check for absolute path
127
+ path = ref.split("#")[0]
128
+
129
+ # This is a self reference and thus the schema does not need to be re-loaded
130
+ if path.nil? || path == ''
131
+ return
132
+ end
133
+
134
+ if path && path[0,1] == '/'
135
+ uri.path = Pathname.new(path).cleanpath.to_s
136
+ else
137
+ uri.path = (Pathname.new(parent_schema.uri.path).parent + path).cleanpath.to_s
138
+ end
139
+ uri.fragment = nil
140
+ end
141
+
142
+ if Validator.schemas[uri.to_s].nil?
143
+ begin
144
+ schema = JSON::Schema.new(JSON::Validator.parse(open(uri.to_s).read), uri, @options[:version])
145
+ Validator.add_schema(schema)
146
+ build_schemas(schema)
147
+ rescue JSON::ParserError
148
+ # Don't rescue this error, we want JSON formatting issues to bubble up
149
+ raise $!
150
+ rescue Exception
151
+ # Failures will occur when this URI cannot be referenced yet. Don't worry about it,
152
+ # the proper error will fall out if the ref isn't ever defined
153
+ end
154
+ end
155
+ end
156
+
157
+
158
+ # Build all schemas with IDs, mapping out the namespace
159
+ def build_schemas(parent_schema)
160
+ # Check for schemas in union types
161
+ ["type", "disallow"].each do |key|
162
+ if parent_schema.schema[key] && parent_schema.schema[key].is_a?(Array)
163
+ parent_schema.schema[key].each_with_index do |type,i|
164
+ if type.is_a?(Hash)
165
+ handle_schema(parent_schema, type)
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ # All properties are schemas
172
+ if parent_schema.schema["properties"]
173
+ parent_schema.schema["properties"].each do |k,v|
174
+ handle_schema(parent_schema, v)
175
+ end
176
+ end
177
+
178
+ # Items are always schemas
179
+ if parent_schema.schema["items"]
180
+ items = parent_schema.schema["items"].clone
181
+ single = false
182
+ if !items.is_a?(Array)
183
+ items = [items]
184
+ single = true
185
+ end
186
+ items.each_with_index do |item,i|
187
+ handle_schema(parent_schema, item)
188
+ end
189
+ end
190
+
191
+ # Each of these might be schemas
192
+ ["additionalProperties", "additionalItems", "dependencies", "extends"].each do |key|
193
+ if parent_schema.schema[key].is_a?(Hash)
194
+ handle_schema(parent_schema, parent_schema.schema[key])
195
+ end
196
+ end
197
+
198
+ end
199
+
200
+ # Either load a reference schema or create a new schema
201
+ def handle_schema(parent_schema, obj)
202
+ if obj['$ref']
203
+ load_ref_schema(parent_schema, obj['$ref'])
204
+ else
205
+ schema_uri = parent_schema.uri.clone
206
+ schema = JSON::Schema.new(obj,schema_uri,@options[:version])
207
+ if obj['id']
208
+ Validator.add_schema(schema)
209
+ end
210
+ build_schemas(schema)
211
+ end
212
+ end
213
+
214
+
215
+ class << self
216
+ def validate(schema, data,opts={})
217
+ begin
218
+ validator = JSON::Validator.new(schema, data, opts)
219
+ validator.validate
220
+ return true
221
+ rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
222
+ return false
223
+ end
224
+ end
225
+
226
+ def validate!(schema, data,opts={})
227
+ validator = JSON::Validator.new(schema, data, opts)
228
+ validator.validate
229
+ end
230
+ alias_method 'validate2', 'validate!'
231
+
232
+ def clear_cache
233
+ @@schemas = {} if @@cache_schemas == false
234
+ end
235
+
236
+ def schemas
237
+ @@schemas
238
+ end
239
+
240
+ def add_schema(schema)
241
+ @@schemas[schema.uri.to_s] = schema if @@schemas[schema.uri.to_s].nil?
242
+ end
243
+
244
+ def cache_schemas=(val)
245
+ @@cache_schemas = val == true ? true : false
246
+ end
247
+
248
+ def validators
249
+ @@validators
250
+ end
251
+
252
+ def default_validator
253
+ @@default_validator
254
+ end
255
+
256
+ def register_validator(v)
257
+ @@validators[v.to_s] = v
258
+ end
259
+
260
+ def register_default_validator(v)
261
+ @@default_validator = v
262
+ end
263
+
264
+ def json_backend
265
+ @@json_backend
266
+ end
267
+
268
+ def json_backend=(backend)
269
+ backend = backend.to_s
270
+ if @@available_json_backend.include?(backend)
271
+ @@json_backend = backend
272
+ else
273
+ raise JSON::Schema::JsonParseError.new("The JSON backend '#{backend}' could not be found.")
274
+ end
275
+ end
276
+
277
+ def parse(s)
278
+ case @@json_backend.to_s
279
+ when 'json'
280
+ JSON.parse(s)
281
+ when 'yajl'
282
+ json = StringIO.new(s)
283
+ parser = Yajl::Parser.new
284
+ parser.parse(json)
285
+ else
286
+ raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json")
287
+ end
288
+ end
289
+ end
290
+
291
+ if Gem.available?('json')
292
+ require 'json'
293
+ @@available_json_backends << 'json'
294
+ @@json_backend = 'json'
295
+ end
296
+
297
+ if Gem.available?('yajl-ruby')
298
+ require 'yajl'
299
+ @@available_json_backends << 'yajl'
300
+ @@json_backend = 'yajl'
301
+ end
302
+
303
+
304
+ private
305
+ <<<<<<< HEAD
306
+
307
+ =======
308
+
309
+ if Gem.available?('uuidtools')
310
+ require 'uuidtools'
311
+ @@fake_uri_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
312
+ else
313
+ require 'uri/uuid'
314
+ @@fake_uri_generator = lambda{|s| UUID.create_v5(s,UUID::Nil).to_s }
315
+ end
316
+
317
+ def fake_uri schema
318
+ @@fake_uri_generator.call(schema)
319
+ end
320
+
321
+ >>>>>>> bcd72ee... added optional dependency on uuidtools gem, to resolve UUID constant overload warning
322
+ def initialize_schema(schema)
323
+ if schema.is_a?(String)
324
+ begin
325
+ # Build a fake URI for this
326
+ schema_uri = URI.parse(fake_uri(schema))
327
+ schema = JSON::Validator.parse(schema)
328
+ if @options[:list]
329
+ schema = {"type" => "array", "items" => schema}
330
+ end
331
+ schema = JSON::Schema.new(schema,schema_uri,@options[:version])
332
+ Validator.add_schema(schema)
333
+ rescue
334
+ # Build a uri for it
335
+ schema_uri = URI.parse(schema)
336
+ if schema_uri.relative?
337
+ # Check for absolute path
338
+ if schema[0,1] == '/'
339
+ schema_uri = URI.parse("file://#{schema}")
340
+ else
341
+ schema_uri = URI.parse("file://#{Dir.pwd}/#{schema}")
342
+ end
343
+ end
344
+ if Validator.schemas[schema_uri.to_s].nil?
345
+ schema = JSON::Validator.parse(open(schema_uri.to_s).read)
346
+ if @options[:list]
347
+ schema = {"type" => "array", "items" => schema}
348
+ end
349
+ schema = JSON::Schema.new(schema,schema_uri,@options[:version])
350
+ Validator.add_schema(schema)
351
+ else
352
+ schema = Validator.schemas[schema_uri.to_s]
353
+ end
354
+ end
355
+ elsif schema.is_a?(Hash)
356
+ if @options[:list]
357
+ schema = {"type" => "array", "items" => schema}
358
+ end
359
+ schema_uri = URI.parse(fake_uri(schema.inspect))
360
+ schema = JSON::Schema.new(schema,schema_uri,@options[:version])
361
+ Validator.add_schema(schema)
362
+ else
363
+ raise "Invalid schema - must be either a string or a hash"
364
+ end
365
+
366
+ schema
367
+ end
368
+
369
+
370
+ def initialize_data(data)
371
+ # Parse the data, if any
372
+ if data.is_a?(String)
373
+ begin
374
+ data = JSON::Validator.parse(data)
375
+ rescue
376
+ json_uri = URI.parse(data)
377
+ if json_uri.relative?
378
+ if data[0,1] == '/'
379
+ schema_uri = URI.parse("file://#{data}")
380
+ else
381
+ schema_uri = URI.parse("file://#{Dir.pwd}/#{data}")
382
+ end
383
+ end
384
+ data = JSON::Validator.parse(open(json_uri.to_s).read)
385
+ end
386
+ end
387
+ data
388
+ end
389
+
390
+ end
391
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-schema
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 57
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 0
10
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kenny Hoxworth
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-19 00:00:00 -04:00
18
+ date: 2011-03-21 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -57,6 +57,7 @@ files:
57
57
  - lib/json-schema/uri/file.rb
58
58
  - lib/json-schema/uri/uuid.rb
59
59
  - lib/json-schema/validator.rb
60
+ - lib/json-schema/validator.rb.orig
60
61
  - lib/json-schema/validators/draft1.rb
61
62
  - lib/json-schema/validators/draft2.rb
62
63
  - lib/json-schema/validators/draft3.rb