Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[472] - Fix for Accept nullable parameter #498

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,18 @@ JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false)
# => false
JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false)

#
# with the `:nullable` option set to true, any key with null value will be evaluated to true
#
schema = {
"type": "object",
"properties": {
"github_url": { "type": "string", "nullable": true }
}
}
# => true
JSON::Validator.validate!(schema, { "github_url" => null })

#
# with the `:parse_integer` option set to false, the integer value given as string will not be parsed.
#
Expand Down
3 changes: 2 additions & 1 deletion lib/json-schema/attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ def self.validation_errors(validator)
'any' => Object,
}

def self.data_valid_for_type?(data, type)
def self.data_valid_for_type?(data, type, nullable: false)
valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true }
valid_classes = [valid_classes, NilClass] if nullable
Copy link

@belinskidima belinskidima Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in case when type is boolean, you need to flatten the valid_classes

type = "boolean"
valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) # => [TrueClass, FalseClass]
valid_classes = [valid_classes, NilClass] if nullable # =>  [[TrueClass, FalseClass], NilClass]
Array(valid_classes).any? { |c| data.is_a?(c) } # => #<TypeError: class or module required>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking this @belinskidima

Array(valid_classes).any? { |c| data.is_a?(c) }
end

Expand Down
4 changes: 3 additions & 1 deletion lib/json-schema/attributes/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ class Schema
class TypeAttribute < Attribute
def self.validate(current_schema, data, fragments, processor, validator, options = {})
union = true
nullable = false
if options[:disallow]
types = current_schema.schema['disallow']
else
types = current_schema.schema['type']
nullable = current_schema.schema['nullable']
end

if !types.is_a?(Array)
Expand All @@ -22,7 +24,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options

types.each_with_index do |type, type_index|
if type.is_a?(String)
valid = data_valid_for_type?(data, type)
valid = data_valid_for_type?(data, type, nullable: nullable)
elsif type.is_a?(Hash) && union
# Validate as a schema
schema = JSON::Schema.new(type, current_schema.uri, validator)
Expand Down
3 changes: 2 additions & 1 deletion lib/json-schema/attributes/type_v4.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ class TypeV4Attribute < Attribute
def self.validate(current_schema, data, fragments, processor, validator, options = {})
union = true
types = current_schema.schema['type']
nullable = current_schema.schema['nullable']
if !types.is_a?(Array)
types = [types]
union = false
end

return if types.any? { |type| data_valid_for_type?(data, type) }
return if types.any? { |type| data_valid_for_type?(data, type, nullable: nullable) }

types = types.map { |type| type.is_a?(String) ? type : '(schema)' }.join(', ')
message = format(
Expand Down
11 changes: 11 additions & 0 deletions test/initialize_data_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,4 +379,15 @@ def test_parse_hash_with_instantiated_validator
assert_raises(TypeError) { v.validate(data) }
assert_raises(TypeError) { v.validate(data) }
end

def test_nullable_param
schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string', 'nullable' => true } } }
data = { 'a' => nil }

assert(JSON::Validator.validate(schema, data))

schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } }

refute(JSON::Validator.validate(schema, data))
end
end