diff --git a/lib/openapi_parser/parameter_validator.rb b/lib/openapi_parser/parameter_validator.rb index e2149b3..3f632fd 100644 --- a/lib/openapi_parser/parameter_validator.rb +++ b/lib/openapi_parser/parameter_validator.rb @@ -11,9 +11,14 @@ def validate_parameter(parameters_hash, params, object_reference, options, is_he params_key_converted = params.keys.map { |k| [convert_key(k, is_header), k] }.to_h parameters_hash.each do |k, v| key = params_key_converted[convert_key(k, is_header)] + array_key = array_key(k) if !is_header && k.end_with?('[]') + if params.include?(key) coerced = v.validate_params(params[key], options) params[key] = coerced if options.coerce_value + elsif !is_header && params.include?(array_key) + coerced = v.validate_params(params[array_key], options) + params[array_key] = coerced if options.coerce_value elsif v.required no_exist_required_key << k end @@ -29,5 +34,9 @@ def validate_parameter(parameters_hash, params, object_reference, options, is_he def convert_key(k, is_header) is_header ? k&.downcase : k end + + def array_key(k) + k.sub(/\[\]$/, '') + end end end diff --git a/spec/data/normal.yml b/spec/data/normal.yml index 368d08c..0740fdb 100644 --- a/spec/data/normal.yml +++ b/spec/data/normal.yml @@ -208,6 +208,15 @@ paths: required: true schema: type: string + - name: query_exploded_integer_list[] + in: query + description: exploded style of integer list + required: false + explode: true + schema: + type: array + items: + type: integer responses: '204': description: no content diff --git a/spec/openapi_parser/parameter_validator_spec.rb b/spec/openapi_parser/parameter_validator_spec.rb index 1fda49d..e046397 100644 --- a/spec/openapi_parser/parameter_validator_spec.rb +++ b/spec/openapi_parser/parameter_validator_spec.rb @@ -20,8 +20,18 @@ end context 'with optional' do - let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1 } } - it { expect(subject).to eq({ 'optional_integer' => 1, 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'query_string' => 'query' }) } + let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1, 'query_exploded_integer_list' => [1, 2] } } + it { expect(subject).to eq({ 'optional_integer' => 1, 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'query_string' => 'query', 'query_exploded_integer_list' => [1, 2] }) } + end + + context 'persist [] suffix if passed in' do + let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1, 'query_exploded_integer_list[]' => [1, 2] } } + it { expect(subject).to eq({ 'optional_integer' => 1, 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'query_string' => 'query', 'query_exploded_integer_list[]' => [1, 2] }) } + end + + context 'ignore array param without [] suffix if passed with' do + let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1, 'query_exploded_integer_list[]' => [1, 2], 'query_exploded_integer_list' => "abc" } } + it { expect(subject).to eq({ 'optional_integer' => 1, 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'query_string' => 'query', 'query_exploded_integer_list[]' => [1, 2], 'query_exploded_integer_list' => "abc" }) } end end @@ -61,6 +71,28 @@ it { expect { subject }.to raise_error(OpenAPIParser::NotNullError) } end end + + context 'invalid items in exploded list' do + let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1, 'query_exploded_integer_list' => ["abc", "def"] } } + + it do + expect { subject }.to raise_error do |e| + expect(e).to be_kind_of(OpenAPIParser::ValidateError) + expect(e.message).to end_with('items expected integer, but received String: "abc"') + end + end + end + + context 'invalid items in exploded list with [] suffix' do + let(:params) { { 'query_string' => 'query', 'query_integer_list' => [1, 2], 'queryString' => 'Query', 'optional_integer' => 1, 'query_exploded_integer_list[]' => ["abc", "def"] } } + + it do + expect { subject }.to raise_error do |e| + expect(e).to be_kind_of(OpenAPIParser::ValidateError) + expect(e.message).to end_with('items expected integer, but received String: "abc"') + end + end + end end end end