json-schema 5.1.1 → 6.2.0
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.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/lib/json-schema/attribute.rb +2 -2
- data/lib/json-schema/attributes/additionalproperties.rb +1 -1
- data/lib/json-schema/attributes/allof.rb +28 -3
- data/lib/json-schema/attributes/anyof.rb +2 -2
- data/lib/json-schema/attributes/const.rb +1 -1
- data/lib/json-schema/attributes/divisibleby.rb +1 -1
- data/lib/json-schema/attributes/enum.rb +1 -1
- data/lib/json-schema/attributes/extends.rb +5 -3
- data/lib/json-schema/attributes/formats/custom.rb +5 -7
- data/lib/json-schema/attributes/formats/date.rb +2 -2
- data/lib/json-schema/attributes/formats/date_time.rb +2 -2
- data/lib/json-schema/attributes/formats/date_time_v4.rb +1 -1
- data/lib/json-schema/attributes/formats/ip.rb +2 -2
- data/lib/json-schema/attributes/formats/time.rb +2 -2
- data/lib/json-schema/attributes/formats/uri.rb +1 -1
- data/lib/json-schema/attributes/limit.rb +2 -2
- data/lib/json-schema/attributes/maxdecimal.rb +1 -1
- data/lib/json-schema/attributes/oneof.rb +7 -7
- data/lib/json-schema/attributes/pattern.rb +1 -1
- data/lib/json-schema/attributes/properties.rb +1 -1
- data/lib/json-schema/attributes/properties_v4.rb +1 -1
- data/lib/json-schema/attributes/ref.rb +13 -12
- data/lib/json-schema/attributes/required.rb +2 -2
- data/lib/json-schema/attributes/type.rb +8 -8
- data/lib/json-schema/attributes/type_v4.rb +2 -2
- data/lib/json-schema/attributes/uniqueitems.rb +1 -1
- data/lib/json-schema/errors/validation_error.rb +5 -4
- data/lib/json-schema/schema/reader.rb +1 -1
- data/lib/json-schema/schema/validator.rb +1 -1
- data/lib/json-schema/schema.rb +10 -10
- data/lib/json-schema/util/array_set.rb +1 -3
- data/lib/json-schema/util/uri.rb +2 -2
- data/lib/json-schema/util/uuid.rb +23 -22
- data/lib/json-schema/validator.rb +107 -55
- data/lib/json-schema.rb +2 -2
- metadata +12 -66
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22afd4889333e3c72db735249ce9f628ebf760c343b98bca7dcf44b5d8aedade
|
|
4
|
+
data.tar.gz: cd6abf52a3af173231e02fec990f2ec80084c8d808ca5f98ef95601fe2c87cf7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 626dc61e7da4ecd5984463bc20a3eadd9551ca5a652cfdc60faf7869e09d0f89aa0676aee7e91135738d0fecef5dda298499d196011bfeb1494a2e9cabe3e946
|
|
7
|
+
data.tar.gz: e111b99ff25a98f785a967b91a3d277f5a0236b5a96bf49cd6c88709abaced71377de17d3f23f206c5d037201a85bd3a1b6d44c685c4e25353f3fc12143da541
|
data/README.md
CHANGED
|
@@ -478,6 +478,14 @@ Optionally, the JSON Schema library supports using the MultiJSON library for
|
|
|
478
478
|
selecting JSON backends. If the MultiJSON library is installed, it will be
|
|
479
479
|
autoloaded.
|
|
480
480
|
|
|
481
|
+
**Deprecation notice:** MultiJSON support is deprecated and will be removed in a
|
|
482
|
+
future version. To stop using MultiJSON, add the following to your application's
|
|
483
|
+
initialization code:
|
|
484
|
+
|
|
485
|
+
```ruby
|
|
486
|
+
JSON::Validator.use_multi_json = false
|
|
487
|
+
```
|
|
488
|
+
|
|
481
489
|
Notes
|
|
482
490
|
-----
|
|
483
491
|
|
|
@@ -9,8 +9,8 @@ module JSON
|
|
|
9
9
|
"#/#{fragments.join('/')}"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors)
|
|
13
|
-
error = ValidationError.new(message, fragments, failed_attribute, current_schema)
|
|
12
|
+
def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors, properties = [])
|
|
13
|
+
error = ValidationError.new(message, fragments, failed_attribute, current_schema, properties)
|
|
14
14
|
if record_errors
|
|
15
15
|
processor.validation_error(error)
|
|
16
16
|
else
|
|
@@ -17,20 +17,45 @@ module JSON
|
|
|
17
17
|
pre_validation_error_count = validation_errors(processor).count
|
|
18
18
|
|
|
19
19
|
begin
|
|
20
|
-
|
|
20
|
+
# Cannot raise if noAdditionalProperties is true, we need to
|
|
21
|
+
# evaluate each sub schema within the allOf, before raising.
|
|
22
|
+
if options[:noAdditionalProperties] == true
|
|
23
|
+
schema.validate(data, fragments, processor, options.merge(record_errors: true))
|
|
24
|
+
else
|
|
25
|
+
schema.validate(data, fragments, processor, options)
|
|
26
|
+
end
|
|
21
27
|
rescue ValidationError => e
|
|
22
28
|
valid = false
|
|
23
29
|
message = e.message
|
|
24
30
|
end
|
|
25
31
|
|
|
26
32
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
33
|
+
|
|
27
34
|
while diff > 0
|
|
28
|
-
diff
|
|
35
|
+
diff -= 1
|
|
29
36
|
errors["allOf ##{schema_index}"].push(validation_errors(processor).pop)
|
|
30
37
|
end
|
|
31
38
|
end
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
# Find any properties that are missing across all subschemas.
|
|
41
|
+
common_missing_properties = {}
|
|
42
|
+
if options[:noAdditionalProperties] == true && !errors.empty?
|
|
43
|
+
all_property_errors = errors.values.flatten.map(&:properties)
|
|
44
|
+
common_missing_properties = (all_property_errors.first || []).to_set
|
|
45
|
+
|
|
46
|
+
all_property_errors[1..].each do |curr_property_errors|
|
|
47
|
+
common_missing_properties &= curr_property_errors.to_set
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# PropertiesV4Attribute represents errors that would indicate an
|
|
52
|
+
# additional property was detected. If we filter these out, we should
|
|
53
|
+
# be left with errors that are not dependent on any other sub schema.
|
|
54
|
+
non_missing_property_errors = errors.values.flatten.reject do |error|
|
|
55
|
+
error.failed_attribute == JSON::Schema::PropertiesV4Attribute
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if !valid || !non_missing_property_errors.empty? || !common_missing_properties.empty?
|
|
34
59
|
message ||= "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match all of the required schemas"
|
|
35
60
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
36
61
|
validation_errors(processor).last.sub_errors = errors
|
|
@@ -27,7 +27,7 @@ module JSON
|
|
|
27
27
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
28
28
|
valid = false if diff > 0
|
|
29
29
|
while diff > 0
|
|
30
|
-
diff
|
|
30
|
+
diff -= 1
|
|
31
31
|
errors["anyOf ##{schema_index}"].push(validation_errors(processor).pop)
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -36,7 +36,7 @@ module JSON
|
|
|
36
36
|
data = original_data
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
unless valid
|
|
40
40
|
message = "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match one or more of the required schemas"
|
|
41
41
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
42
42
|
validation_errors(processor).last.sub_errors = errors
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class ConstAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
const_value = current_schema.schema['const']
|
|
8
8
|
unless const_value == data
|
|
9
9
|
message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match constant '#{const_value}'"
|
|
@@ -7,7 +7,7 @@ module JSON
|
|
|
7
7
|
'divisibleBy'
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
10
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
11
11
|
return unless data.is_a?(Numeric)
|
|
12
12
|
|
|
13
13
|
factor = current_schema.schema[keyword]
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class EnumAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
enum = current_schema.schema['enum']
|
|
8
8
|
return if enum.include?(data)
|
|
9
9
|
|
|
@@ -6,7 +6,7 @@ module JSON
|
|
|
6
6
|
class ExtendsAttribute < Attribute
|
|
7
7
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
|
8
8
|
schemas = current_schema.schema['extends']
|
|
9
|
-
schemas = [schemas]
|
|
9
|
+
schemas = [schemas] unless schemas.is_a?(Array)
|
|
10
10
|
schemas.each do |s|
|
|
11
11
|
uri, schema = get_extended_uri_and_schema(s, current_schema, validator)
|
|
12
12
|
if schema
|
|
@@ -22,7 +22,8 @@ module JSON
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def self.get_extended_uri_and_schema(s, current_schema, validator)
|
|
25
|
-
uri
|
|
25
|
+
uri = nil
|
|
26
|
+
schema = nil
|
|
26
27
|
|
|
27
28
|
if s.is_a?(Hash)
|
|
28
29
|
uri = current_schema.uri
|
|
@@ -30,7 +31,8 @@ module JSON
|
|
|
30
31
|
ref_uri, ref_schema = JSON::Schema::RefAttribute.get_referenced_uri_and_schema(s, current_schema, validator)
|
|
31
32
|
if ref_schema
|
|
32
33
|
if s.size == 1 # Check if anything else apart from $ref
|
|
33
|
-
uri
|
|
34
|
+
uri = ref_uri
|
|
35
|
+
schema = ref_schema
|
|
34
36
|
else
|
|
35
37
|
s = s.dup
|
|
36
38
|
s.delete '$ref'
|
|
@@ -8,13 +8,11 @@ module JSON
|
|
|
8
8
|
@validation_proc = validation_proc
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def validate(current_schema, data, fragments, processor,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
self.class.validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
17
|
-
end
|
|
11
|
+
def validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
12
|
+
@validation_proc.call data
|
|
13
|
+
rescue JSON::Schema::CustomFormatError => e
|
|
14
|
+
message = "The property '#{self.class.build_fragment(fragments)}' #{e.message}"
|
|
15
|
+
self.class.validation_error(processor, message, fragments, current_schema, self.class, options[:record_errors])
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
end
|
|
@@ -3,9 +3,9 @@ require 'json-schema/attributes/format'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class DateFormat < FormatAttribute
|
|
6
|
-
REGEXP = /\A\d{4}-\d{2}-\d{2}\z
|
|
6
|
+
REGEXP = /\A\d{4}-\d{2}-\d{2}\z/.freeze
|
|
7
7
|
|
|
8
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
8
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
9
9
|
if data.is_a?(String)
|
|
10
10
|
error_message = "The property '#{build_fragment(fragments)}' must be a date in the format of YYYY-MM-DD"
|
|
11
11
|
if REGEXP.match(data)
|
|
@@ -3,9 +3,9 @@ require 'json-schema/attributes/format'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class DateTimeFormat < FormatAttribute
|
|
6
|
-
REGEXP = /\A\d{4}-\d{2}-\d{2}T(\d{2}):(\d{2}):(\d{2})([
|
|
6
|
+
REGEXP = /\A\d{4}-\d{2}-\d{2}T(\d{2}):(\d{2}):(\d{2})([.,]\d+)?(Z|[+-](\d{2})(:?\d{2})?)?\z/.freeze
|
|
7
7
|
|
|
8
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
8
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
9
9
|
# Timestamp in restricted ISO-8601 YYYY-MM-DDThh:mm:ssZ with optional decimal fraction of the second
|
|
10
10
|
if data.is_a?(String)
|
|
11
11
|
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"
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attributes/format'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class DateTimeV4Format < FormatAttribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(String)
|
|
8
8
|
|
|
9
9
|
DateTime.rfc3339(data)
|
|
@@ -5,7 +5,7 @@ require 'socket'
|
|
|
5
5
|
module JSON
|
|
6
6
|
class Schema
|
|
7
7
|
class IPFormat < FormatAttribute
|
|
8
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
8
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
9
9
|
return unless data.is_a?(String)
|
|
10
10
|
|
|
11
11
|
begin
|
|
@@ -14,7 +14,7 @@ module JSON
|
|
|
14
14
|
raise e unless e.message.start_with?('invalid address')
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
family = ip_version == 6 ? Socket::AF_INET6 : Socket::AF_INET
|
|
17
|
+
family = (ip_version == 6) ? Socket::AF_INET6 : Socket::AF_INET
|
|
18
18
|
unless ip && ip.family == family
|
|
19
19
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv#{ip_version} address"
|
|
20
20
|
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
|
@@ -3,9 +3,9 @@ require 'json-schema/attributes/format'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class TimeFormat < FormatAttribute
|
|
6
|
-
REGEXP = /\A(\d{2}):(\d{2}):(\d{2})\z
|
|
6
|
+
REGEXP = /\A(\d{2}):(\d{2}):(\d{2})\z/.freeze
|
|
7
7
|
|
|
8
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
8
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
9
9
|
if data.is_a?(String)
|
|
10
10
|
error_message = "The property '#{build_fragment(fragments)}' must be a time in the format of hh:mm:ss"
|
|
11
11
|
if (m = REGEXP.match(data))
|
|
@@ -4,7 +4,7 @@ require 'json-schema/errors/uri_error'
|
|
|
4
4
|
module JSON
|
|
5
5
|
class Schema
|
|
6
6
|
class UriFormat < FormatAttribute
|
|
7
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
7
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
8
8
|
return unless data.is_a?(String)
|
|
9
9
|
|
|
10
10
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid URI"
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class LimitAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
schema = current_schema.schema
|
|
8
8
|
return unless data.is_a?(acceptable_type) && invalid?(schema, value(data))
|
|
9
9
|
|
|
@@ -28,7 +28,7 @@ module JSON
|
|
|
28
28
|
schema[limit_name]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def self.exclusive?(
|
|
31
|
+
def self.exclusive?(_schema)
|
|
32
32
|
false
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class MaxDecimalAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(Numeric)
|
|
8
8
|
|
|
9
9
|
max_decimal_places = current_schema.schema['maxDecimal']
|
|
@@ -27,9 +27,9 @@ module JSON
|
|
|
27
27
|
|
|
28
28
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
29
29
|
valid = false if diff > 0
|
|
30
|
-
validation_error_count += 1
|
|
30
|
+
validation_error_count += 1 unless valid
|
|
31
31
|
while diff > 0
|
|
32
|
-
diff
|
|
32
|
+
diff -= 1
|
|
33
33
|
errors["oneOf ##{schema_index}"].push(validation_errors(processor).pop)
|
|
34
34
|
end
|
|
35
35
|
data = original_data
|
|
@@ -40,11 +40,11 @@ module JSON
|
|
|
40
40
|
return
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
if validation_error_count == one_of.length
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
message = if validation_error_count == one_of.length
|
|
44
|
+
"The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match any of the required schemas"
|
|
45
|
+
else
|
|
46
|
+
"The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} matched more than one of the required schemas"
|
|
47
|
+
end
|
|
48
48
|
|
|
49
49
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) if message
|
|
50
50
|
validation_errors(processor).last.sub_errors = errors if message
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class PatternAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(String)
|
|
8
8
|
|
|
9
9
|
pattern = current_schema.schema['pattern']
|
|
@@ -58,7 +58,7 @@ module JSON
|
|
|
58
58
|
unless diff.empty?
|
|
59
59
|
properties = diff.keys.join(', ')
|
|
60
60
|
message = "The property '#{build_fragment(fragments)}' contained undefined properties: '#{properties}'"
|
|
61
|
-
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
61
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors], diff.keys)
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -5,7 +5,7 @@ module JSON
|
|
|
5
5
|
class PropertiesV4Attribute < PropertiesAttribute
|
|
6
6
|
# draft4 relies on its own RequiredAttribute validation at a higher level, rather than
|
|
7
7
|
# as an attribute of individual properties.
|
|
8
|
-
def self.required?(
|
|
8
|
+
def self.required?(_schema, options)
|
|
9
9
|
options[:allPropertiesRequired] == true
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -20,7 +20,8 @@ module JSON
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def self.get_referenced_uri_and_schema(s, current_schema, validator)
|
|
23
|
-
uri
|
|
23
|
+
uri = nil
|
|
24
|
+
schema = nil
|
|
24
25
|
|
|
25
26
|
temp_uri = JSON::Util::URI.normalize_ref(s['$ref'], current_schema.uri)
|
|
26
27
|
|
|
@@ -35,17 +36,17 @@ module JSON
|
|
|
35
36
|
fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split('/')
|
|
36
37
|
fragment_path = ''
|
|
37
38
|
fragments.each do |fragment|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
next unless fragment && fragment != ''
|
|
40
|
+
|
|
41
|
+
fragment = fragment.gsub('~0', '~').gsub('~1', '/')
|
|
42
|
+
target_schema = if target_schema.is_a?(Array)
|
|
43
|
+
target_schema[fragment.to_i]
|
|
44
|
+
else
|
|
45
|
+
target_schema[fragment]
|
|
46
|
+
end
|
|
47
|
+
fragment_path += "/#{fragment}"
|
|
48
|
+
if target_schema.nil?
|
|
49
|
+
raise SchemaError, "The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri}"
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class RequiredAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(Hash)
|
|
8
8
|
|
|
9
9
|
schema = current_schema.schema
|
|
@@ -18,7 +18,7 @@ module JSON
|
|
|
18
18
|
!defined_properties[property]['default'].nil? &&
|
|
19
19
|
!defined_properties[property]['readonly']
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
unless prop_defaults
|
|
22
22
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
|
23
23
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
24
24
|
end
|
|
@@ -5,13 +5,13 @@ module JSON
|
|
|
5
5
|
class TypeAttribute < Attribute
|
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
|
7
7
|
union = true
|
|
8
|
-
if options[:disallow]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
types = if options[:disallow]
|
|
9
|
+
current_schema.schema['disallow']
|
|
10
|
+
else
|
|
11
|
+
current_schema.schema['type']
|
|
12
|
+
end
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
unless types.is_a?(Array)
|
|
15
15
|
types = [types]
|
|
16
16
|
union = false
|
|
17
17
|
end
|
|
@@ -41,7 +41,7 @@ module JSON
|
|
|
41
41
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
42
42
|
valid = false if diff > 0
|
|
43
43
|
while diff > 0
|
|
44
|
-
diff
|
|
44
|
+
diff -= 1
|
|
45
45
|
union_errors["type ##{type_index}"].push(validation_errors(processor).pop)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -50,7 +50,7 @@ module JSON
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
if options[:disallow]
|
|
53
|
-
return
|
|
53
|
+
return unless valid
|
|
54
54
|
|
|
55
55
|
message = "The property '#{build_fragment(fragments)}' matched one or more of the following types: #{list_types(types)}"
|
|
56
56
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
@@ -3,10 +3,10 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class TypeV4Attribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
union = true
|
|
8
8
|
types = current_schema.schema['type']
|
|
9
|
-
|
|
9
|
+
unless types.is_a?(Array)
|
|
10
10
|
types = [types]
|
|
11
11
|
union = false
|
|
12
12
|
end
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class UniqueItemsAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(Array)
|
|
8
8
|
|
|
9
9
|
if data.clone.uniq!
|
|
@@ -2,20 +2,21 @@ module JSON
|
|
|
2
2
|
class Schema
|
|
3
3
|
class ValidationError < StandardError
|
|
4
4
|
INDENT = ' '
|
|
5
|
-
attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message
|
|
5
|
+
attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message, :properties
|
|
6
6
|
|
|
7
|
-
def initialize(message, fragments, failed_attribute, schema)
|
|
7
|
+
def initialize(message, fragments, failed_attribute, schema, properties = [])
|
|
8
8
|
@fragments = fragments.clone
|
|
9
9
|
@schema = schema
|
|
10
10
|
@sub_errors = {}
|
|
11
11
|
@failed_attribute = failed_attribute
|
|
12
12
|
@message = message
|
|
13
|
+
@properties = properties
|
|
13
14
|
super(message_with_schema)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def to_string(subschema_level = 0)
|
|
17
18
|
if @sub_errors.empty?
|
|
18
|
-
subschema_level == 0 ? message_with_schema : message
|
|
19
|
+
(subschema_level == 0) ? message_with_schema : message
|
|
19
20
|
else
|
|
20
21
|
messages = ["#{message}. The schema specific errors were:\n"]
|
|
21
22
|
@sub_errors.each do |subschema, errors|
|
|
@@ -28,7 +29,7 @@ module JSON
|
|
|
28
29
|
|
|
29
30
|
def to_hash
|
|
30
31
|
base = { schema: @schema.uri, fragment: ::JSON::Schema::Attribute.build_fragment(fragments), message: message_with_schema, failed_attribute: @failed_attribute.to_s.split(':').last.split('Attribute').first }
|
|
31
|
-
|
|
32
|
+
unless @sub_errors.empty?
|
|
32
33
|
base[:errors] = @sub_errors.each_with_object({}) do |(subschema, errors), hsh|
|
|
33
34
|
subschema_sym = subschema.downcase.gsub(/\W+/, '_').to_sym
|
|
34
35
|
hsh[subschema_sym] = Array(errors).map { |e| e.to_hash }
|
data/lib/json-schema/schema.rb
CHANGED
|
@@ -19,13 +19,13 @@ module JSON
|
|
|
19
19
|
@uri = JSON::Util::URI.strip_fragment(@uri)
|
|
20
20
|
|
|
21
21
|
# If there is a $schema on this schema, use it to determine which validator to use
|
|
22
|
-
if @schema['$schema']
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
@validator = if @schema['$schema']
|
|
23
|
+
JSON::Validator.validator_for_uri(@schema['$schema'])
|
|
24
|
+
elsif parent_validator
|
|
25
|
+
parent_validator
|
|
26
|
+
else
|
|
27
|
+
JSON::Validator.default_validator
|
|
28
|
+
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def validate(data, fragments, processor, options = {})
|
|
@@ -34,13 +34,13 @@ module JSON
|
|
|
34
34
|
|
|
35
35
|
def self.stringify(schema)
|
|
36
36
|
case schema
|
|
37
|
-
when Hash
|
|
37
|
+
when Hash
|
|
38
38
|
schema.map { |key, _value| [key.to_s, stringify(schema[key])] }.to_h
|
|
39
|
-
when Array
|
|
39
|
+
when Array
|
|
40
40
|
schema.map do |schema_item|
|
|
41
41
|
stringify(schema_item)
|
|
42
42
|
end
|
|
43
|
-
when Symbol
|
|
43
|
+
when Symbol
|
|
44
44
|
schema.to_s
|
|
45
45
|
else
|
|
46
46
|
schema
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
|
|
3
1
|
# This is a hack that I don't want to ever use anywhere else or repeat EVER, but we need enums to be
|
|
4
2
|
# an Array to pass schema validation. But we also want fast lookup!
|
|
5
3
|
|
|
6
4
|
class ArraySet < Array
|
|
7
5
|
def include?(obj)
|
|
8
|
-
|
|
6
|
+
unless defined? @values
|
|
9
7
|
@values = Set.new
|
|
10
8
|
each { |x| @values << convert_to_float_if_numeric(x) }
|
|
11
9
|
end
|
data/lib/json-schema/util/uri.rb
CHANGED
|
@@ -6,7 +6,7 @@ module JSON
|
|
|
6
6
|
module Util
|
|
7
7
|
# @api private
|
|
8
8
|
class URI < Addressable::URI
|
|
9
|
-
SUPPORTED_PROTOCOLS = %w
|
|
9
|
+
SUPPORTED_PROTOCOLS = %w[http https ftp tftp sftp ssh svn+ssh telnet nntp gopher wais ldap prospero]
|
|
10
10
|
|
|
11
11
|
class << self
|
|
12
12
|
alias unescape_uri unescape
|
|
@@ -14,7 +14,7 @@ module JSON
|
|
|
14
14
|
# @param uri [String, Addressable::URI]
|
|
15
15
|
# @return [Addressable::URI, nil]
|
|
16
16
|
def parse(uri)
|
|
17
|
-
super
|
|
17
|
+
super
|
|
18
18
|
rescue Addressable::URI::InvalidURIError => e
|
|
19
19
|
raise JSON::Schema::UriError, e.message
|
|
20
20
|
end
|
|
@@ -36,7 +36,7 @@ module JSON
|
|
|
36
36
|
private_class_method :new
|
|
37
37
|
|
|
38
38
|
class << self
|
|
39
|
-
def mask
|
|
39
|
+
def mask(v, str)
|
|
40
40
|
nstr = str.bytes.to_a
|
|
41
41
|
version = [0, 16, 32, 48, 64, 80][v]
|
|
42
42
|
nstr[6] &= 0b00001111
|
|
@@ -54,7 +54,7 @@ module JSON
|
|
|
54
54
|
|
|
55
55
|
# UUID generation using SHA1. Recommended over create_md5.
|
|
56
56
|
# Namespace object is another UUID, some of them are pre-defined below.
|
|
57
|
-
def create_sha1
|
|
57
|
+
def create_sha1(str, namespace)
|
|
58
58
|
sha1 = Digest::SHA1.new
|
|
59
59
|
sha1.update namespace.raw_bytes
|
|
60
60
|
sha1.update str
|
|
@@ -64,10 +64,10 @@ module JSON
|
|
|
64
64
|
ret.freeze
|
|
65
65
|
ret
|
|
66
66
|
end
|
|
67
|
-
alias
|
|
67
|
+
alias create_v5 create_sha1
|
|
68
68
|
|
|
69
69
|
# UUID generation using MD5 (for backward compat.)
|
|
70
|
-
def create_md5
|
|
70
|
+
def create_md5(str, namespace)
|
|
71
71
|
md5 = Digest::MD5.new
|
|
72
72
|
md5.update namespace.raw_bytes
|
|
73
73
|
md5.update str
|
|
@@ -77,7 +77,7 @@ module JSON
|
|
|
77
77
|
ret.freeze
|
|
78
78
|
ret
|
|
79
79
|
end
|
|
80
|
-
alias
|
|
80
|
+
alias create_v3 create_md5
|
|
81
81
|
|
|
82
82
|
# UUID generation using random-number generator. From it's random
|
|
83
83
|
# nature, there's no warranty that the created ID is really universaly
|
|
@@ -94,14 +94,14 @@ module JSON
|
|
|
94
94
|
ret.freeze
|
|
95
95
|
ret
|
|
96
96
|
end
|
|
97
|
-
alias
|
|
97
|
+
alias create_v4 create_random
|
|
98
98
|
|
|
99
|
-
def read_state
|
|
99
|
+
def read_state(fp) # :nodoc:
|
|
100
100
|
fp.rewind
|
|
101
101
|
Marshal.load fp.read
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
def write_state
|
|
104
|
+
def write_state(fp, c, m) # :nodoc:
|
|
105
105
|
fp.rewind
|
|
106
106
|
str = Marshal.dump [c, m]
|
|
107
107
|
fp.write str
|
|
@@ -117,10 +117,10 @@ module JSON
|
|
|
117
117
|
# invokation. If you want to speed this up, try remounting tmpdir with a
|
|
118
118
|
# memory based filesystem (such as tmpfs). STILL slow? then no way but
|
|
119
119
|
# rewrite it with c :)
|
|
120
|
-
def create
|
|
120
|
+
def create(clock = nil, time = nil, mac_addr = nil)
|
|
121
121
|
c = t = m = nil
|
|
122
122
|
Dir.chdir Dir.tmpdir do
|
|
123
|
-
unless FileTest.exist? STATE_FILE
|
|
123
|
+
unless FileTest.exist? STATE_FILE
|
|
124
124
|
# Generate a pseudo MAC address because we have no pure-ruby way
|
|
125
125
|
# to know the MAC address of the NIC this system uses. Note
|
|
126
126
|
# that cheating with pseudo arresses here is completely legal:
|
|
@@ -150,10 +150,10 @@ module JSON
|
|
|
150
150
|
c = clock % 0x4000 if clock
|
|
151
151
|
m = mac_addr if mac_addr
|
|
152
152
|
t = time
|
|
153
|
-
if t.nil?
|
|
153
|
+
if t.nil?
|
|
154
154
|
# UUID epoch is 1582/Oct/15
|
|
155
155
|
tt = Time.now
|
|
156
|
-
t = (tt.to_i *
|
|
156
|
+
t = (tt.to_i * 10_000_000) + (tt.tv_usec * 10) + 0x01B21DD213814000
|
|
157
157
|
end
|
|
158
158
|
c = c.succ # important; increment here
|
|
159
159
|
write_state fp, c, m
|
|
@@ -162,21 +162,21 @@ module JSON
|
|
|
162
162
|
|
|
163
163
|
tl = t & 0xFFFF_FFFF
|
|
164
164
|
tm = t >> 32
|
|
165
|
-
tm
|
|
165
|
+
tm &= 0xFFFF
|
|
166
166
|
th = t >> 48
|
|
167
|
-
th
|
|
168
|
-
th
|
|
167
|
+
th &= 0x0FFF
|
|
168
|
+
th |= 0x1000
|
|
169
169
|
cl = c & 0xFF
|
|
170
170
|
ch = c & 0x3F00
|
|
171
|
-
ch
|
|
172
|
-
ch
|
|
171
|
+
ch >>= 8
|
|
172
|
+
ch |= 0x80
|
|
173
173
|
pack tl, tm, th, cl, ch, m
|
|
174
174
|
end
|
|
175
|
-
alias
|
|
175
|
+
alias create_v1 create
|
|
176
176
|
|
|
177
177
|
# A simple GUID parser: just ignores unknown characters and convert
|
|
178
178
|
# hexadecimal dump into 16-octet object.
|
|
179
|
-
def parse
|
|
179
|
+
def parse(obj)
|
|
180
180
|
str = obj.to_s.sub(/\Aurn:uuid:/, '')
|
|
181
181
|
str.gsub!(/[^0-9A-Fa-f]/, '')
|
|
182
182
|
raw = str[0..31].lines.to_a.pack 'H*'
|
|
@@ -187,7 +187,7 @@ module JSON
|
|
|
187
187
|
|
|
188
188
|
# The 'primitive constructor' of this class
|
|
189
189
|
# Note UUID.pack(uuid.unpack) == uuid
|
|
190
|
-
def pack
|
|
190
|
+
def pack(tl, tm, th, ch, cl, n)
|
|
191
191
|
raw = [tl, tm, th, ch, cl, n].pack 'NnnCCa6'
|
|
192
192
|
ret = new raw
|
|
193
193
|
ret.freeze
|
|
@@ -238,13 +238,14 @@ module JSON
|
|
|
238
238
|
# Two UUIDs are said to be equal if and only if their (byte-order
|
|
239
239
|
# canonicalized) integer representations are equivalent. Refer RFC4122 for
|
|
240
240
|
# details.
|
|
241
|
-
def ==
|
|
241
|
+
def ==(other)
|
|
242
242
|
to_i == other.to_i
|
|
243
243
|
end
|
|
244
244
|
|
|
245
245
|
include Comparable
|
|
246
|
+
|
|
246
247
|
# UUIDs are comparable (don't know what benefits are there, though).
|
|
247
|
-
def <=>
|
|
248
|
+
def <=>(other)
|
|
248
249
|
to_s <=> other.to_s
|
|
249
250
|
end
|
|
250
251
|
|
|
@@ -3,10 +3,10 @@ require 'pathname'
|
|
|
3
3
|
require 'bigdecimal'
|
|
4
4
|
require 'digest/sha1'
|
|
5
5
|
require 'date'
|
|
6
|
-
require 'thread'
|
|
7
6
|
require 'timeout'
|
|
8
7
|
require 'stringio'
|
|
9
8
|
require 'yaml'
|
|
9
|
+
require 'delegate'
|
|
10
10
|
|
|
11
11
|
require 'json-schema/schema/reader'
|
|
12
12
|
require 'json-schema/errors/schema_error'
|
|
@@ -38,11 +38,12 @@ module JSON
|
|
|
38
38
|
@@available_json_backends = []
|
|
39
39
|
@@json_backend = nil
|
|
40
40
|
@@serializer = nil
|
|
41
|
+
@@use_multi_json = defined?(MultiJson) ? true : false
|
|
42
|
+
@@multi_json_warned = false
|
|
41
43
|
@@mutex = Mutex.new
|
|
42
44
|
|
|
43
45
|
def initialize(schema_data, opts = {})
|
|
44
46
|
@options = @@default_opts.clone.merge(opts)
|
|
45
|
-
@errors = []
|
|
46
47
|
|
|
47
48
|
configured_validator = self.class.validator_for_name(@options[:version])
|
|
48
49
|
@options[:schema_reader] ||= self.class.schema_reader
|
|
@@ -108,24 +109,47 @@ module JSON
|
|
|
108
109
|
end
|
|
109
110
|
end
|
|
110
111
|
|
|
112
|
+
class ErrorRecorder < SimpleDelegator
|
|
113
|
+
def initialize(sub)
|
|
114
|
+
@errors = []
|
|
115
|
+
|
|
116
|
+
super
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def validation_error(error)
|
|
120
|
+
@errors.push(error)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def validation_errors
|
|
124
|
+
@errors
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def with_errors
|
|
128
|
+
self
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def with_errors
|
|
133
|
+
ErrorRecorder.new(self)
|
|
134
|
+
end
|
|
135
|
+
|
|
111
136
|
# Run a simple true/false validation of data against a schema
|
|
112
137
|
def validate(data)
|
|
113
138
|
original_data = data
|
|
114
139
|
data = initialize_data(data)
|
|
115
|
-
|
|
140
|
+
error_recorder = with_errors
|
|
141
|
+
@base_schema.validate(data, [], error_recorder, @validation_options)
|
|
116
142
|
|
|
117
143
|
if @options[:record_errors]
|
|
118
144
|
if @options[:errors_as_objects]
|
|
119
|
-
|
|
145
|
+
error_recorder.validation_errors.map { |e| e.to_hash }
|
|
120
146
|
else
|
|
121
|
-
|
|
147
|
+
error_recorder.validation_errors.map { |e| e.to_string }
|
|
122
148
|
end
|
|
123
149
|
else
|
|
124
150
|
true
|
|
125
151
|
end
|
|
126
152
|
ensure
|
|
127
|
-
@errors = []
|
|
128
|
-
|
|
129
153
|
if @validation_options[:clear_cache] == true
|
|
130
154
|
self.class.clear_cache
|
|
131
155
|
end
|
|
@@ -166,11 +190,11 @@ module JSON
|
|
|
166
190
|
|
|
167
191
|
# Check for schemas in union types
|
|
168
192
|
%w[type disallow].each do |key|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
193
|
+
next unless schema[key].is_a?(Array)
|
|
194
|
+
|
|
195
|
+
schema[key].each do |type|
|
|
196
|
+
if type.is_a?(Hash)
|
|
197
|
+
handle_schema(parent_schema, type)
|
|
174
198
|
end
|
|
175
199
|
end
|
|
176
200
|
end
|
|
@@ -229,21 +253,11 @@ module JSON
|
|
|
229
253
|
end
|
|
230
254
|
end
|
|
231
255
|
|
|
232
|
-
def validation_error(error)
|
|
233
|
-
@errors.push(error)
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def validation_errors
|
|
237
|
-
@errors
|
|
238
|
-
end
|
|
239
|
-
|
|
240
256
|
class << self
|
|
241
257
|
def validate(schema, data, opts = {})
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
false
|
|
246
|
-
end
|
|
258
|
+
validate!(schema, data, opts)
|
|
259
|
+
rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
|
|
260
|
+
false
|
|
247
261
|
end
|
|
248
262
|
|
|
249
263
|
def validate_json(schema, data, opts = {})
|
|
@@ -327,7 +341,7 @@ module JSON
|
|
|
327
341
|
|
|
328
342
|
def cache_schemas=(val)
|
|
329
343
|
warn '[DEPRECATION NOTICE] Schema caching is now a validation option. Schemas will still be cached if this is set to true, but this method will be removed in version >= 3. Please use the :clear_cache validation option instead.'
|
|
330
|
-
@@cache_schemas = val == true
|
|
344
|
+
@@cache_schemas = val == true
|
|
331
345
|
end
|
|
332
346
|
|
|
333
347
|
def validators
|
|
@@ -399,8 +413,20 @@ module JSON
|
|
|
399
413
|
end
|
|
400
414
|
end
|
|
401
415
|
|
|
416
|
+
def use_multi_json?
|
|
417
|
+
@@use_multi_json
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def use_multi_json=(value)
|
|
421
|
+
@@use_multi_json = value ? true : false
|
|
422
|
+
if use_multi_json? == false
|
|
423
|
+
ensure_ruby_json_backends!
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
402
427
|
def json_backend
|
|
403
|
-
if
|
|
428
|
+
if use_multi_json?
|
|
429
|
+
multi_json_deprecation_warning!
|
|
404
430
|
MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
|
|
405
431
|
else
|
|
406
432
|
@@json_backend
|
|
@@ -408,8 +434,9 @@ module JSON
|
|
|
408
434
|
end
|
|
409
435
|
|
|
410
436
|
def json_backend=(backend)
|
|
411
|
-
if
|
|
412
|
-
|
|
437
|
+
if use_multi_json?
|
|
438
|
+
multi_json_deprecation_warning!
|
|
439
|
+
backend = 'json_gem' if backend == 'json'
|
|
413
440
|
MultiJson.respond_to?(:use) ? MultiJson.use(backend) : MultiJson.engine = backend
|
|
414
441
|
else
|
|
415
442
|
backend = backend.to_s
|
|
@@ -422,7 +449,8 @@ module JSON
|
|
|
422
449
|
end
|
|
423
450
|
|
|
424
451
|
def parse(s)
|
|
425
|
-
if
|
|
452
|
+
if use_multi_json?
|
|
453
|
+
multi_json_deprecation_warning!
|
|
426
454
|
begin
|
|
427
455
|
MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
|
|
428
456
|
rescue MultiJson::ParseError => e
|
|
@@ -469,8 +497,12 @@ module JSON
|
|
|
469
497
|
end
|
|
470
498
|
end
|
|
471
499
|
|
|
472
|
-
|
|
473
|
-
if
|
|
500
|
+
def ensure_ruby_json_backends!
|
|
501
|
+
if !@@available_json_backends.empty? || !@@serializer.nil?
|
|
502
|
+
return
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
if Gem::Specification.find_all_by_name('json').any?
|
|
474
506
|
require 'json'
|
|
475
507
|
@@available_json_backends << 'json'
|
|
476
508
|
@@json_backend = 'json'
|
|
@@ -484,41 +516,61 @@ module JSON
|
|
|
484
516
|
end
|
|
485
517
|
end
|
|
486
518
|
|
|
487
|
-
if Gem::Specification
|
|
519
|
+
if Gem::Specification.find_all_by_name('yajl-ruby').any?
|
|
488
520
|
require 'yajl'
|
|
489
521
|
@@available_json_backends << 'yajl'
|
|
490
522
|
@@json_backend = 'yajl'
|
|
491
523
|
end
|
|
492
524
|
|
|
493
|
-
if @@json_backend == 'yajl'
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
525
|
+
@@serializer = if @@json_backend == 'yajl'
|
|
526
|
+
->(o) { Yajl::Encoder.encode(o) }
|
|
527
|
+
elsif @@json_backend == 'json'
|
|
528
|
+
->(o) { JSON.dump(o) }
|
|
529
|
+
else
|
|
530
|
+
->(o) { YAML.dump(o) }
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def multi_json_deprecation_warning!
|
|
535
|
+
unless @@multi_json_warned
|
|
536
|
+
@@multi_json_warned = true
|
|
537
|
+
warn '[DEPRECATION NOTICE] json-schema support for MultiJSON is deprecated and will be removed in a future version. ' \
|
|
538
|
+
'To stop using MultiJSON, add `JSON::Validator.use_multi_json = false` to your application\'s initialization code.'
|
|
499
539
|
end
|
|
500
540
|
end
|
|
541
|
+
|
|
542
|
+
private
|
|
543
|
+
|
|
544
|
+
# for test usage only
|
|
545
|
+
def reset_multi_json_deprecation_warning!
|
|
546
|
+
@@multi_json_warned = false
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
if use_multi_json? == false
|
|
551
|
+
ensure_ruby_json_backends!
|
|
501
552
|
end
|
|
502
553
|
|
|
503
554
|
private
|
|
504
555
|
|
|
505
|
-
if Gem::Specification
|
|
556
|
+
if Gem::Specification.find_all_by_name('uuidtools').any?
|
|
506
557
|
require 'uuidtools'
|
|
507
|
-
@@fake_uuid_generator =
|
|
558
|
+
@@fake_uuid_generator = ->(s) { UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
|
|
508
559
|
else
|
|
509
560
|
require 'json-schema/util/uuid'
|
|
510
|
-
@@fake_uuid_generator =
|
|
561
|
+
@@fake_uuid_generator = ->(s) { JSON::Util::UUID.create_v5(s, JSON::Util::UUID::Nil).to_s }
|
|
511
562
|
end
|
|
512
563
|
|
|
513
|
-
def serialize
|
|
514
|
-
if
|
|
564
|
+
def serialize(schema)
|
|
565
|
+
if self.class.use_multi_json?
|
|
566
|
+
self.class.multi_json_deprecation_warning!
|
|
515
567
|
MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema)
|
|
516
568
|
else
|
|
517
569
|
@@serializer.call(schema)
|
|
518
570
|
end
|
|
519
571
|
end
|
|
520
572
|
|
|
521
|
-
def fake_uuid
|
|
573
|
+
def fake_uuid(schema)
|
|
522
574
|
@@fake_uuid_generator.call(schema)
|
|
523
575
|
end
|
|
524
576
|
|
|
@@ -535,7 +587,15 @@ module JSON
|
|
|
535
587
|
rescue JSON::Schema::JsonParseError
|
|
536
588
|
# Build a uri for it
|
|
537
589
|
schema_uri = Util::URI.normalized_uri(schema)
|
|
538
|
-
if
|
|
590
|
+
if self.class.schema_loaded?(schema_uri)
|
|
591
|
+
schema = self.class.schema_for_uri(schema_uri)
|
|
592
|
+
if @options[:list] && @options[:fragment].nil?
|
|
593
|
+
schema = schema.to_array_schema
|
|
594
|
+
schema.uri = JSON::Util::URI.parse(fake_uuid(serialize(schema.schema)))
|
|
595
|
+
self.class.add_schema(schema)
|
|
596
|
+
end
|
|
597
|
+
schema
|
|
598
|
+
else
|
|
539
599
|
schema = @options[:schema_reader].read(schema_uri)
|
|
540
600
|
schema = JSON::Schema.stringify(schema)
|
|
541
601
|
|
|
@@ -544,14 +604,6 @@ module JSON
|
|
|
544
604
|
end
|
|
545
605
|
|
|
546
606
|
self.class.add_schema(schema)
|
|
547
|
-
else
|
|
548
|
-
schema = self.class.schema_for_uri(schema_uri)
|
|
549
|
-
if @options[:list] && @options[:fragment].nil?
|
|
550
|
-
schema = schema.to_array_schema
|
|
551
|
-
schema.uri = JSON::Util::URI.parse(fake_uuid(serialize(schema.schema)))
|
|
552
|
-
self.class.add_schema(schema)
|
|
553
|
-
end
|
|
554
|
-
schema
|
|
555
607
|
end
|
|
556
608
|
end
|
|
557
609
|
elsif schema.is_a?(Hash)
|
|
@@ -580,7 +632,7 @@ module JSON
|
|
|
580
632
|
begin
|
|
581
633
|
# Check if the string is valid integer
|
|
582
634
|
strict_convert = data.match?(/\A[+-]?\d+\z/) && !@options[:parse_integer]
|
|
583
|
-
data =
|
|
635
|
+
data = self.class.parse(data) unless strict_convert
|
|
584
636
|
rescue JSON::Schema::JsonParseError
|
|
585
637
|
begin
|
|
586
638
|
json_uri = Util::URI.normalized_uri(data)
|
data/lib/json-schema.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
|
|
3
|
-
if Gem::Specification
|
|
3
|
+
if Gem::Specification.find_all_by_name('multi_json').any?
|
|
4
4
|
require 'multi_json'
|
|
5
5
|
|
|
6
6
|
# Force MultiJson to load an engine before we define the JSON constant here; otherwise,
|
|
@@ -14,5 +14,5 @@ require 'json-schema/schema'
|
|
|
14
14
|
require 'json-schema/schema/reader'
|
|
15
15
|
require 'json-schema/validator'
|
|
16
16
|
|
|
17
|
-
Dir[File.join(File.dirname(__FILE__), 'json-schema/attributes/**/*.rb')].each { |file| require file }
|
|
17
|
+
Dir[File.join(File.dirname(__FILE__), 'json-schema/attributes/**/*.rb')].sort.each { |file| require file }
|
|
18
18
|
Dir[File.join(File.dirname(__FILE__), 'json-schema/validators/*.rb')].sort!.each { |file| require file }
|
metadata
CHANGED
|
@@ -1,72 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json-schema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kenny Hoxworth
|
|
8
8
|
- Vox Pupuli
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
|
-
- !ruby/object:Gem::Dependency
|
|
15
|
-
name: minitest
|
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
requirements:
|
|
18
|
-
- - "~>"
|
|
19
|
-
- !ruby/object:Gem::Version
|
|
20
|
-
version: '5.0'
|
|
21
|
-
type: :development
|
|
22
|
-
prerelease: false
|
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
-
requirements:
|
|
25
|
-
- - "~>"
|
|
26
|
-
- !ruby/object:Gem::Version
|
|
27
|
-
version: '5.0'
|
|
28
|
-
- !ruby/object:Gem::Dependency
|
|
29
|
-
name: rake
|
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
|
31
|
-
requirements:
|
|
32
|
-
- - "~>"
|
|
33
|
-
- !ruby/object:Gem::Version
|
|
34
|
-
version: '13.0'
|
|
35
|
-
type: :development
|
|
36
|
-
prerelease: false
|
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
-
requirements:
|
|
39
|
-
- - "~>"
|
|
40
|
-
- !ruby/object:Gem::Version
|
|
41
|
-
version: '13.0'
|
|
42
|
-
- !ruby/object:Gem::Dependency
|
|
43
|
-
name: voxpupuli-rubocop
|
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
|
45
|
-
requirements:
|
|
46
|
-
- - "~>"
|
|
47
|
-
- !ruby/object:Gem::Version
|
|
48
|
-
version: 3.0.0
|
|
49
|
-
type: :development
|
|
50
|
-
prerelease: false
|
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
-
requirements:
|
|
53
|
-
- - "~>"
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
55
|
-
version: 3.0.0
|
|
56
|
-
- !ruby/object:Gem::Dependency
|
|
57
|
-
name: webmock
|
|
58
|
-
requirement: !ruby/object:Gem::Requirement
|
|
59
|
-
requirements:
|
|
60
|
-
- - "~>"
|
|
61
|
-
- !ruby/object:Gem::Version
|
|
62
|
-
version: '3.23'
|
|
63
|
-
type: :development
|
|
64
|
-
prerelease: false
|
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
-
requirements:
|
|
67
|
-
- - "~>"
|
|
68
|
-
- !ruby/object:Gem::Version
|
|
69
|
-
version: '3.23'
|
|
70
13
|
- !ruby/object:Gem::Dependency
|
|
71
14
|
name: addressable
|
|
72
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -85,23 +28,28 @@ dependencies:
|
|
|
85
28
|
name: bigdecimal
|
|
86
29
|
requirement: !ruby/object:Gem::Requirement
|
|
87
30
|
requirements:
|
|
88
|
-
- - "
|
|
31
|
+
- - ">="
|
|
89
32
|
- !ruby/object:Gem::Version
|
|
90
33
|
version: '3.1'
|
|
34
|
+
- - "<"
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: '5'
|
|
91
37
|
type: :runtime
|
|
92
38
|
prerelease: false
|
|
93
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
94
40
|
requirements:
|
|
95
|
-
- - "
|
|
41
|
+
- - ">="
|
|
96
42
|
- !ruby/object:Gem::Version
|
|
97
43
|
version: '3.1'
|
|
98
|
-
|
|
44
|
+
- - "<"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '5'
|
|
99
47
|
email: voxpupuli@groups.io
|
|
100
48
|
executables: []
|
|
101
49
|
extensions: []
|
|
102
50
|
extra_rdoc_files:
|
|
103
|
-
- README.md
|
|
104
51
|
- LICENSE.md
|
|
52
|
+
- README.md
|
|
105
53
|
files:
|
|
106
54
|
- LICENSE.md
|
|
107
55
|
- README.md
|
|
@@ -194,7 +142,6 @@ metadata:
|
|
|
194
142
|
changelog_uri: https://github.com/voxpupuli/json-schema//blob/master/CHANGELOG.md
|
|
195
143
|
bug_tracker_uri: https://github.com/voxpupuli/json-schema//issues
|
|
196
144
|
funding_uri: https://github.com/sponsors/voxpupuli
|
|
197
|
-
post_install_message:
|
|
198
145
|
rdoc_options: []
|
|
199
146
|
require_paths:
|
|
200
147
|
- lib
|
|
@@ -209,8 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
209
156
|
- !ruby/object:Gem::Version
|
|
210
157
|
version: '0'
|
|
211
158
|
requirements: []
|
|
212
|
-
rubygems_version:
|
|
213
|
-
signing_key:
|
|
159
|
+
rubygems_version: 4.0.3
|
|
214
160
|
specification_version: 4
|
|
215
161
|
summary: Ruby JSON Schema Validator
|
|
216
162
|
test_files: []
|