json-schema 0.9.0 → 0.9.1

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.
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