json-schema 1.0.5 → 1.0.6
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 +1 -1
- data/lib/json-schema.rb +2 -2
- data/lib/json-schema/attributes/format.rb +3 -3
- data/lib/json-schema/validator.rb +50 -13
- data/test/test_files.rb +12 -4
- data/test/test_full_validation.rb +61 -0
- data/test/test_jsonschema_draft3.rb +46 -0
- metadata +2 -2
data/README.textile
CHANGED
data/lib/json-schema.rb
CHANGED
@@ -11,7 +11,7 @@ if begin
|
|
11
11
|
|
12
12
|
# Force MultiJson to load an engine before we define the JSON constant here; otherwise,
|
13
13
|
# it looks for things that are under the JSON namespace that aren't there (since we have defined it here)
|
14
|
-
MultiJson.engine
|
14
|
+
MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
|
15
15
|
end
|
16
16
|
|
17
17
|
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/json-schema"
|
@@ -21,4 +21,4 @@ require 'schema'
|
|
21
21
|
require 'validator'
|
22
22
|
Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/*.rb")].each {|file| require file }
|
23
23
|
Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].each {|file| require file }
|
24
|
-
require 'uri/file'
|
24
|
+
require 'uri/file'
|
@@ -4,12 +4,12 @@ module JSON
|
|
4
4
|
def self.validate(current_schema, data, fragments, validator, options = {})
|
5
5
|
case current_schema.schema['format']
|
6
6
|
|
7
|
-
# Timestamp in restricted ISO-8601 YYYY-MM-DDThh:mm:ssZ
|
7
|
+
# Timestamp in restricted ISO-8601 YYYY-MM-DDThh:mm:ssZ with optional decimal fraction of the second
|
8
8
|
when 'date-time'
|
9
9
|
if data.is_a?(String)
|
10
|
-
error_message = "The property '#{build_fragment(fragments)}' must be a date/time in the ISO-8601 format of YYYY-MM-DDThh:mm:ssZ"
|
10
|
+
error_message = "The property '#{build_fragment(fragments)}' must be a date/time in the ISO-8601 format of YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss.ssZ"
|
11
11
|
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
12
|
-
r = Regexp.new('^\d\d\d\d-\d\d-\d\dT(\d\d):(\d\d):(\d\d)Z$')
|
12
|
+
r = Regexp.new('^\d\d\d\d-\d\d-\d\dT(\d\d):(\d\d):(\d\d)([\.,]\d+)?Z$')
|
13
13
|
if (m = r.match(data))
|
14
14
|
parts = data.split("T")
|
15
15
|
begin
|
@@ -296,6 +296,14 @@ module JSON
|
|
296
296
|
end
|
297
297
|
end
|
298
298
|
|
299
|
+
def validate_json(schema, data, opts={})
|
300
|
+
validate(schema, data, opts.merge(:json => true))
|
301
|
+
end
|
302
|
+
|
303
|
+
def validate_uri(schema, data, opts={})
|
304
|
+
validate(schema, data, opts.merge(:uri => true))
|
305
|
+
end
|
306
|
+
|
299
307
|
def validate!(schema, data,opts={})
|
300
308
|
validator = JSON::Validator.new(schema, data, opts)
|
301
309
|
validator.validate
|
@@ -303,6 +311,13 @@ module JSON
|
|
303
311
|
end
|
304
312
|
alias_method 'validate2', 'validate!'
|
305
313
|
|
314
|
+
def validate_json!(schema, data, opts={})
|
315
|
+
validate!(schema, data, opts.merge(:json => true))
|
316
|
+
end
|
317
|
+
|
318
|
+
def validate_uri!(schema, data, opts={})
|
319
|
+
validate!(schema, data, opts.merge(:uri => true))
|
320
|
+
end
|
306
321
|
|
307
322
|
def fully_validate(schema, data, opts={})
|
308
323
|
opts[:record_errors] = true
|
@@ -316,6 +331,13 @@ module JSON
|
|
316
331
|
fully_validate(schema, data, opts)
|
317
332
|
end
|
318
333
|
|
334
|
+
def fully_validate_json(schema, data, opts={})
|
335
|
+
fully_validate(schema, data, opts.merge(:json => true))
|
336
|
+
end
|
337
|
+
|
338
|
+
def fully_validate_uri(schema, data, opts={})
|
339
|
+
fully_validate(schema, data, opts.merge(:uri => true))
|
340
|
+
end
|
319
341
|
|
320
342
|
def clear_cache
|
321
343
|
@@schemas = {} if @@cache_schemas == false
|
@@ -363,7 +385,7 @@ module JSON
|
|
363
385
|
|
364
386
|
def json_backend
|
365
387
|
if defined?(MultiJson)
|
366
|
-
MultiJson.engine
|
388
|
+
MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
|
367
389
|
else
|
368
390
|
@@json_backend
|
369
391
|
end
|
@@ -372,7 +394,7 @@ module JSON
|
|
372
394
|
def json_backend=(backend)
|
373
395
|
if defined?(MultiJson)
|
374
396
|
backend = backend == 'json' ? 'json_gem' : backend
|
375
|
-
MultiJson.engine = backend
|
397
|
+
MultiJson.respond_to?(:use) ? MultiJson.use(backend) : MultiJson.engine = backend
|
376
398
|
else
|
377
399
|
backend = backend.to_s
|
378
400
|
if @@available_json_backends.include?(backend)
|
@@ -385,7 +407,7 @@ module JSON
|
|
385
407
|
|
386
408
|
def parse(s)
|
387
409
|
if defined?(MultiJson)
|
388
|
-
MultiJson.decode(s)
|
410
|
+
MultiJson.respond_to?(:load) ? MultiJson.load(s) : MultiJson.decode(s)
|
389
411
|
else
|
390
412
|
case @@json_backend.to_s
|
391
413
|
when 'json'
|
@@ -451,7 +473,7 @@ module JSON
|
|
451
473
|
|
452
474
|
def serialize schema
|
453
475
|
if defined?(MultiJson)
|
454
|
-
MultiJson.encode(schema)
|
476
|
+
MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema)
|
455
477
|
else
|
456
478
|
@@serializer.call(schema)
|
457
479
|
end
|
@@ -510,20 +532,35 @@ module JSON
|
|
510
532
|
|
511
533
|
|
512
534
|
def initialize_data(data)
|
513
|
-
|
514
|
-
|
535
|
+
if @options[:json]
|
536
|
+
data = JSON::Validator.parse(data)
|
537
|
+
elsif @options[:uri]
|
538
|
+
json_uri = URI.parse(data)
|
539
|
+
if json_uri.relative?
|
540
|
+
if data[0,1] == '/'
|
541
|
+
json_uri = URI.parse("file://#{data}")
|
542
|
+
else
|
543
|
+
json_uri = URI.parse("file://#{Dir.pwd}/#{data}")
|
544
|
+
end
|
545
|
+
end
|
546
|
+
data = JSON::Validator.parse(open(json_uri.to_s).read)
|
547
|
+
elsif data.is_a?(String)
|
515
548
|
begin
|
516
549
|
data = JSON::Validator.parse(data)
|
517
550
|
rescue
|
518
|
-
|
519
|
-
|
520
|
-
if
|
521
|
-
|
522
|
-
|
523
|
-
|
551
|
+
begin
|
552
|
+
json_uri = URI.parse(data)
|
553
|
+
if json_uri.relative?
|
554
|
+
if data[0,1] == '/'
|
555
|
+
json_uri = URI.parse("file://#{data}")
|
556
|
+
else
|
557
|
+
json_uri = URI.parse("file://#{Dir.pwd}/#{data}")
|
558
|
+
end
|
524
559
|
end
|
560
|
+
data = JSON::Validator.parse(open(json_uri.to_s).read)
|
561
|
+
rescue
|
562
|
+
# Silently discard the error - the data will not change
|
525
563
|
end
|
526
|
-
data = JSON::Validator.parse(open(json_uri.to_s).read)
|
527
564
|
end
|
528
565
|
end
|
529
566
|
data
|
data/test/test_files.rb
CHANGED
@@ -16,13 +16,21 @@ class JSONSchemaTest < Test::Unit::TestCase
|
|
16
16
|
|
17
17
|
def test_data_from_file
|
18
18
|
schema = {"type" => "object", "properties" => {"a" => {"type" => "integer"}}}
|
19
|
-
assert(JSON::Validator.
|
20
|
-
assert(!JSON::Validator.
|
19
|
+
assert(JSON::Validator.validate_uri(schema,File.join(File.dirname(__FILE__),"data/good_data_1.json")))
|
20
|
+
assert(!JSON::Validator.validate_uri(schema,File.join(File.dirname(__FILE__),"data/bad_data_1.json")))
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_data_from_json
|
24
|
+
if JSON::Validator.json_backend != nil
|
25
|
+
schema = {"type" => "object", "properties" => {"a" => {"type" => "integer"}}}
|
26
|
+
assert(JSON::Validator.validate_json(schema, %Q({"a" : 5})))
|
27
|
+
assert(!JSON::Validator.validate_json(schema, %Q({"a" : "poop"})))
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
def test_both_from_file
|
24
|
-
assert(JSON::Validator.
|
25
|
-
assert(!JSON::Validator.
|
32
|
+
assert(JSON::Validator.validate_uri(File.join(File.dirname(__FILE__),"schemas/good_schema_1.json"),File.join(File.dirname(__FILE__),"data/good_data_1.json")))
|
33
|
+
assert(!JSON::Validator.validate_uri(File.join(File.dirname(__FILE__),"schemas/good_schema_1.json"),File.join(File.dirname(__FILE__),"data/bad_data_1.json")))
|
26
34
|
end
|
27
35
|
|
28
36
|
def test_file_ref
|
@@ -145,4 +145,65 @@ class JSONFullValidation < Test::Unit::TestCase
|
|
145
145
|
assert(errors[1][:failed_attribute] == "Type")
|
146
146
|
assert(errors[1][:fragment] == "#/c")
|
147
147
|
end
|
148
|
+
|
149
|
+
def test_full_validation_with_nested_required_properties
|
150
|
+
schema = {
|
151
|
+
"$schema" => "http://json-schema.org/draft-03/schema#",
|
152
|
+
"type" => "object",
|
153
|
+
"properties" => {
|
154
|
+
"x" => {
|
155
|
+
"required" => true,
|
156
|
+
"type" => "object",
|
157
|
+
"properties" => {
|
158
|
+
"a" => {"type"=>"integer","required"=>true},
|
159
|
+
"b" => {"type"=>"integer","required"=>true},
|
160
|
+
"c" => {"type"=>"integer","required"=>false},
|
161
|
+
"d" => {"type"=>"integer","required"=>false},
|
162
|
+
"e" => {"type"=>"integer","required"=>false},
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
data = {"x" => {"a"=>5, "d"=>5, "e"=>"what?"}}
|
168
|
+
|
169
|
+
errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
|
170
|
+
assert_equal 2, errors.length
|
171
|
+
assert_equal '#/x', errors[0][:fragment]
|
172
|
+
assert_equal 'Properties', errors[0][:failed_attribute]
|
173
|
+
assert_equal '#/x/e', errors[1][:fragment]
|
174
|
+
assert_equal 'Type', errors[1][:failed_attribute]
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_full_validation_with_nested_required_propertiesin_array
|
178
|
+
schema = {
|
179
|
+
"$schema" => "http://json-schema.org/draft-03/schema#",
|
180
|
+
"type" => "object",
|
181
|
+
"properties" => {
|
182
|
+
"x" => {
|
183
|
+
"required" => true,
|
184
|
+
"type" => "array",
|
185
|
+
"items" => {
|
186
|
+
"type" => "object",
|
187
|
+
"properties" => {
|
188
|
+
"a" => {"type"=>"integer","required"=>true},
|
189
|
+
"b" => {"type"=>"integer","required"=>true},
|
190
|
+
"c" => {"type"=>"integer","required"=>false},
|
191
|
+
"d" => {"type"=>"integer","required"=>false},
|
192
|
+
"e" => {"type"=>"integer","required"=>false},
|
193
|
+
}
|
194
|
+
}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
missing_b= {"a"=>5}
|
199
|
+
e_is_wrong_type= {"a"=>5,"b"=>5,"e"=>"what?"}
|
200
|
+
data = {"x" => [missing_b, e_is_wrong_type]}
|
201
|
+
|
202
|
+
errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
|
203
|
+
assert_equal 2, errors.length
|
204
|
+
assert_equal '#/x/0', errors[0][:fragment]
|
205
|
+
assert_equal 'Properties', errors[0][:failed_attribute]
|
206
|
+
assert_equal '#/x/1/e', errors[1][:fragment]
|
207
|
+
assert_equal 'Type', errors[1][:failed_attribute]
|
208
|
+
end
|
148
209
|
end
|
@@ -28,6 +28,8 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
28
28
|
data['a'] = true
|
29
29
|
assert(!JSON::Validator.validate(schema,data))
|
30
30
|
|
31
|
+
assert(JSON::Validator.validate({'type' => 'integer'}, 3))
|
32
|
+
assert(!JSON::Validator.validate({'type' => 'integer'}, "hello"))
|
31
33
|
|
32
34
|
# Test numbers
|
33
35
|
schema["properties"]["a"]["type"] = "number"
|
@@ -43,6 +45,10 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
43
45
|
data['a'] = true
|
44
46
|
assert(!JSON::Validator.validate(schema,data))
|
45
47
|
|
48
|
+
assert(JSON::Validator.validate({'type' => 'number'}, 3))
|
49
|
+
assert(JSON::Validator.validate({'type' => 'number'}, 3.14159265358979))
|
50
|
+
assert(!JSON::Validator.validate({'type' => 'number'}, "hello"))
|
51
|
+
|
46
52
|
|
47
53
|
# Test strings
|
48
54
|
schema["properties"]["a"]["type"] = "string"
|
@@ -58,6 +64,10 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
58
64
|
data['a'] = true
|
59
65
|
assert(!JSON::Validator.validate(schema,data))
|
60
66
|
|
67
|
+
assert(JSON::Validator.validate({'type' => 'string'}, 'hello'))
|
68
|
+
assert(!JSON::Validator.validate({'type' => 'string'}, 3.14159265358979))
|
69
|
+
assert(!JSON::Validator.validate({'type' => 'string'}, []))
|
70
|
+
|
61
71
|
|
62
72
|
# Test booleans
|
63
73
|
schema["properties"]["a"]["type"] = "boolean"
|
@@ -76,6 +86,12 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
76
86
|
data['a'] = false
|
77
87
|
assert(JSON::Validator.validate(schema,data))
|
78
88
|
|
89
|
+
assert(JSON::Validator.validate({'type' => 'boolean'}, true))
|
90
|
+
assert(JSON::Validator.validate({'type' => 'boolean'}, false))
|
91
|
+
assert(!JSON::Validator.validate({'type' => 'boolean'}, nil))
|
92
|
+
assert(!JSON::Validator.validate({'type' => 'boolean'}, 3))
|
93
|
+
assert(!JSON::Validator.validate({'type' => 'boolean'}, "hello"))
|
94
|
+
|
79
95
|
|
80
96
|
# Test object
|
81
97
|
schema["properties"]["a"]["type"] = "object"
|
@@ -91,6 +107,12 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
91
107
|
data['a'] = true
|
92
108
|
assert(!JSON::Validator.validate(schema,data))
|
93
109
|
|
110
|
+
assert(JSON::Validator.validate({'type' => 'objec'}, {'a' => true}))
|
111
|
+
assert(JSON::Validator.validate({'type' => 'object'}, {}))
|
112
|
+
assert(!JSON::Validator.validate({'type' => 'object'}, []))
|
113
|
+
assert(!JSON::Validator.validate({'type' => 'object'}, 3))
|
114
|
+
assert(!JSON::Validator.validate({'type' => 'object'}, "hello"))
|
115
|
+
|
94
116
|
|
95
117
|
# Test array
|
96
118
|
schema["properties"]["a"]["type"] = "array"
|
@@ -106,6 +128,12 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
106
128
|
data['a'] = true
|
107
129
|
assert(!JSON::Validator.validate(schema,data))
|
108
130
|
|
131
|
+
assert(JSON::Validator.validate({'type' => 'array'}, ['a']))
|
132
|
+
assert(JSON::Validator.validate({'type' => 'array'}, []))
|
133
|
+
assert(!JSON::Validator.validate({'type' => 'array'}, {}))
|
134
|
+
assert(!JSON::Validator.validate({'type' => 'array'}, 3))
|
135
|
+
assert(!JSON::Validator.validate({'type' => 'array'}, "hello"))
|
136
|
+
|
109
137
|
|
110
138
|
# Test null
|
111
139
|
schema["properties"]["a"]["type"] = "null"
|
@@ -121,6 +149,11 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
121
149
|
data['a'] = true
|
122
150
|
assert(!JSON::Validator.validate(schema,data))
|
123
151
|
|
152
|
+
assert(JSON::Validator.validate({'type' => 'null'}, nil))
|
153
|
+
assert(!JSON::Validator.validate({'type' => 'null'}, false))
|
154
|
+
assert(!JSON::Validator.validate({'type' => 'null'}, []))
|
155
|
+
assert(!JSON::Validator.validate({'type' => 'null'}, "hello"))
|
156
|
+
|
124
157
|
|
125
158
|
# Test any
|
126
159
|
schema["properties"]["a"]["type"] = "any"
|
@@ -136,6 +169,12 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
136
169
|
data['a'] = true
|
137
170
|
assert(JSON::Validator.validate(schema,data))
|
138
171
|
|
172
|
+
assert(JSON::Validator.validate({'type' => 'any'}, true))
|
173
|
+
assert(JSON::Validator.validate({'type' => 'any'}, nil))
|
174
|
+
assert(JSON::Validator.validate({'type' => 'any'}, {}))
|
175
|
+
assert(JSON::Validator.validate({'type' => 'any'}, 3))
|
176
|
+
assert(JSON::Validator.validate({'type' => 'any'}, "hello"))
|
177
|
+
|
139
178
|
|
140
179
|
# Test a union type
|
141
180
|
schema["properties"]["a"]["type"] = ["integer","string"]
|
@@ -148,6 +187,9 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
148
187
|
data["a"] = false
|
149
188
|
assert(!JSON::Validator.validate(schema,data))
|
150
189
|
|
190
|
+
assert(JSON::Validator.validate({'type' => ['string', 'null']}, "hello"))
|
191
|
+
assert(!JSON::Validator.validate({'type' => ['integer', 'object']}, "hello"))
|
192
|
+
|
151
193
|
# Test a union type with schemas
|
152
194
|
schema["properties"]["a"]["type"] = [{ "type" => "string" }, {"type" => "object", "properties" => {"b" => {"type" => "integer"}}}]
|
153
195
|
|
@@ -883,6 +925,10 @@ class JSONSchemaDraft3Test < Test::Unit::TestCase
|
|
883
925
|
|
884
926
|
data = {"a" => "2010-01-01T12:00:00Z"}
|
885
927
|
assert(JSON::Validator.validate(schema,data))
|
928
|
+
data = {"a" => "2010-01-01T12:00:00.1Z"}
|
929
|
+
assert(JSON::Validator.validate(schema,data))
|
930
|
+
data = {"a" => "2010-01-01T12:00:00,1Z"}
|
931
|
+
assert(JSON::Validator.validate(schema,data))
|
886
932
|
data = {"a" => "2010-01-32T12:00:00Z"}
|
887
933
|
assert(!JSON::Validator.validate(schema,data))
|
888
934
|
data = {"a" => "2010-13-01T12:00:00Z"}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: hoxworth@gmail.com
|