diff --git a/README.md b/README.md index f3ba221..db27912 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ request_operation.path_params # => {"template_name"=>"1"} # coerce parameter -root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'), {coerce_value: true, datetime_coerce_class: DateTime}) +root = OpenAPIParser.parse(YAML.load_file('open_api_3/schema.yml'), {coerce_value: true, datetime_coerce_class: DateTime, date_coerce_class: Date}) request_operation = root.request_operation(:get, '/string_params_coercer') request_operation.validate_request_parameter({'integer_1' => '1', 'datetime_string' => '2016-04-01T16:00:00+09:00'}) # => {"integer_1"=>1, "datetime_string"=># diff --git a/lib/openapi_parser/config.rb b/lib/openapi_parser/config.rb index c92cebe..68cc182 100644 --- a/lib/openapi_parser/config.rb +++ b/lib/openapi_parser/config.rb @@ -19,6 +19,10 @@ def datetime_coerce_class @config[:datetime_coerce_class] end + def date_coerce_class + @config[:date_coerce_class] + end + def coerce_value @config[:coerce_value] end @@ -46,6 +50,7 @@ def request_validator_options @request_validator_options ||= OpenAPIParser::SchemaValidator::Options.new(allow_empty_date_and_datetime: allow_empty_date_and_datetime, coerce_value: coerce_value, datetime_coerce_class: datetime_coerce_class, + date_coerce_class: date_coerce_class, validate_header: validate_header) end diff --git a/lib/openapi_parser/schema_validator.rb b/lib/openapi_parser/schema_validator.rb index 9f3f2d0..f95c492 100644 --- a/lib/openapi_parser/schema_validator.rb +++ b/lib/openapi_parser/schema_validator.rb @@ -56,6 +56,7 @@ def initialize(value, schema, options) @allow_empty_date_and_datetime = options.allow_empty_date_and_datetime @coerce_value = options.coerce_value @datetime_coerce_class = options.datetime_coerce_class + @date_coerce_class = options.date_coerce_class end # execute validate data @@ -121,7 +122,7 @@ def validator(value, schema) end def string_validator - @string_validator ||= OpenAPIParser::SchemaValidator::StringValidator.new(self, @allow_empty_date_and_datetime, @coerce_value, @datetime_coerce_class) + @string_validator ||= OpenAPIParser::SchemaValidator::StringValidator.new(self, @allow_empty_date_and_datetime, @coerce_value, @datetime_coerce_class, @date_coerce_class) end def integer_validator diff --git a/lib/openapi_parser/schema_validator/options.rb b/lib/openapi_parser/schema_validator/options.rb index 9d12371..35b8b56 100644 --- a/lib/openapi_parser/schema_validator/options.rb +++ b/lib/openapi_parser/schema_validator/options.rb @@ -6,14 +6,17 @@ class Options # @return [Boolean] coerce value option on/off # @!attribute [r] datetime_coerce_class # @return [Object, nil] coerce datetime string by this Object class + # @!attribute [r] date_coerce_class + # @return [Object, nil] coerce date string by this Object class # @!attribute [r] validate_header # @return [Boolean] validate header or not - attr_reader :allow_empty_date_and_datetime, :coerce_value, :datetime_coerce_class, :validate_header + attr_reader :allow_empty_date_and_datetime, :coerce_value, :datetime_coerce_class, :validate_header, :date_coerce_class - def initialize(allow_empty_date_and_datetime: false, coerce_value: nil, datetime_coerce_class: nil, validate_header: true) + def initialize(allow_empty_date_and_datetime: false, coerce_value: nil, datetime_coerce_class: nil, validate_header: true, date_coerce_class: nil) @allow_empty_date_and_datetime = allow_empty_date_and_datetime @coerce_value = coerce_value @datetime_coerce_class = datetime_coerce_class + @date_coerce_class = date_coerce_class @validate_header = validate_header end end diff --git a/lib/openapi_parser/schema_validator/string_validator.rb b/lib/openapi_parser/schema_validator/string_validator.rb index 79dad3e..0b3aadc 100644 --- a/lib/openapi_parser/schema_validator/string_validator.rb +++ b/lib/openapi_parser/schema_validator/string_validator.rb @@ -2,10 +2,11 @@ class OpenAPIParser::SchemaValidator class StringValidator < Base include ::OpenAPIParser::SchemaValidator::Enumable - def initialize(validator, allow_empty_date_and_datetime, coerce_value, datetime_coerce_class) + def initialize(validator, allow_empty_date_and_datetime, coerce_value, datetime_coerce_class, date_coerce_class) super(validator, coerce_value) @allow_empty_date_and_datetime = allow_empty_date_and_datetime @datetime_coerce_class = datetime_coerce_class + @date_coerce_class = date_coerce_class end def coerce_and_validate(value, schema, **_keyword_args) @@ -90,16 +91,18 @@ def validate_date_format(value, schema) return [nil, OpenAPIParser::InvalidDateFormat.new(value, schema.object_reference)] unless value =~ /^\d{4}-\d{2}-\d{2}$/ begin - parsed_date = Date.iso8601(value) + if @date_coerce_class.nil? + # validate only + Date.iso8601(value) + [value, nil] + else + # validate and coerce + [@date_coerce_class.iso8601(value), nil] + end rescue ArgumentError - return [nil, OpenAPIParser::InvalidDateFormat.new(value, schema.object_reference)] - end - - unless parsed_date.strftime('%Y-%m-%d') == value - return [nil, OpenAPIParser::InvalidDateFormat.new(value, schema.object_reference)] + # when rfc3339(value) failed + [nil, OpenAPIParser::InvalidDateFormat.new(value, schema.object_reference)] end - - return [value, nil] end def validate_datetime_format(value, schema) diff --git a/sig/openapi_parser/config.rbs b/sig/openapi_parser/config.rbs index bd85248..944abac 100644 --- a/sig/openapi_parser/config.rbs +++ b/sig/openapi_parser/config.rbs @@ -9,6 +9,7 @@ module OpenAPIParser def initialize: (untyped config) -> untyped def allow_empty_date_and_datetime: -> bool + def date_coerce_class: -> (singleton(Object) | nil) def datetime_coerce_class: -> (singleton(Object) | nil) def coerce_value: -> bool def expand_reference: -> bool diff --git a/sig/openapi_parser/schema_validator.rbs b/sig/openapi_parser/schema_validator.rbs index 777fe44..160c999 100644 --- a/sig/openapi_parser/schema_validator.rbs +++ b/sig/openapi_parser/schema_validator.rbs @@ -6,6 +6,7 @@ module OpenAPIParser @schema: OpenAPIParser::Schemas::Schema @coerce_value: bool | nil @datetime_coerce_class: singleton(Object) | nil + @date_coerce_class: singleton(Object) | nil @string_validator: OpenAPIParser::SchemaValidator::StringValidator | nil @integer_validator: OpenAPIParser::SchemaValidator::IntegerValidator | nil @float_validator: OpenAPIParser::SchemaValidator::FloatValidator | nil diff --git a/sig/openapi_parser/schema_validators/options.rbs b/sig/openapi_parser/schema_validators/options.rbs index 68fbcbe..853be1b 100644 --- a/sig/openapi_parser/schema_validators/options.rbs +++ b/sig/openapi_parser/schema_validators/options.rbs @@ -6,7 +6,7 @@ module OpenAPIParser attr_reader coerce_value: bool | nil attr_reader datetime_coerce_class: singleton(Object) | nil attr_reader validate_header: bool - def initialize: (?allow_empty_date_and_datetime: bool | nil, ?coerce_value: bool | nil, ?datetime_coerce_class: singleton(Object) | nil, ?validate_header: bool) -> untyped + def initialize: (?allow_empty_date_and_datetime: bool | nil, ?coerce_value: bool | nil, ?datetime_coerce_class: singleton(Object) | nil, ?date_coerce_class: singleton(Object) | nil, ?validate_header: bool) -> untyped end class ResponseValidateOptions diff --git a/spec/openapi_parser/schema_validator/string_validator_spec.rb b/spec/openapi_parser/schema_validator/string_validator_spec.rb index 767c711..a5aaf5a 100644 --- a/spec/openapi_parser/schema_validator/string_validator_spec.rb +++ b/spec/openapi_parser/schema_validator/string_validator_spec.rb @@ -224,8 +224,24 @@ end context 'correct' do + let(:options) { ::OpenAPIParser::SchemaValidator::Options.new(coerce_value: true, date_coerce_class: date_coerce_class) } let(:params) { { 'date_str' => '2021-02-12' } } - it { expect(subject).to eq({ 'date_str' => '2021-02-12' }) } + + context 'when date_coerce_class is nil' do + let(:date_coerce_class) { nil } + + it 'return String' do + expect(subject).to eq({ 'date_str' => '2021-02-12' }) + end + end + + context 'when date_coerce_class is Date' do + let(:date_coerce_class) { Date } + + it 'return Date' do + expect(subject).to eq({ 'date_str' => Date.iso8601('2021-02-12') }) + end + end end context 'invalid' do