@@ -52,6 +52,8 @@ def deserialize_params_by_location(raw_params, location)
5252 # If no parameters are defined for this location, return raw params as-is
5353 return raw_params if params_for_location . empty?
5454
55+ raw_params = normalize_raw_params ( raw_params , location , params_for_location )
56+
5557 # Collect parameter names that will be deserialized
5658 # This includes both the parameter name and any properties (for exploded objects)
5759 deserialized_keys = Set . new
@@ -105,6 +107,65 @@ def convert_to_indifferent_hash(hash)
105107 Committee ::Utils . indifferent_hash . merge ( hash )
106108 end
107109
110+ # Normalize Rack-style nested query hashes into bracket notation when the
111+ # schema expects bracket-named params or deepObject query params.
112+ # Example: { "filter" => { "slug" => "/test" } } => { "filter[slug]" => "/test" }
113+ # @param [Hash] raw_params
114+ # @param [String] location
115+ # @param [Array<OpenAPIParser::Schemas::Parameter>] params_for_location
116+ # @return [Hash]
117+ def normalize_raw_params ( raw_params , location , params_for_location )
118+ return raw_params unless location == 'query'
119+ return raw_params unless raw_params . values . any? { |value | value . is_a? ( Hash ) }
120+ return raw_params unless requires_query_param_flattening? ( params_for_location )
121+
122+ normalized = Committee ::Utils . indifferent_hash
123+
124+ raw_params . each do |key , value |
125+ if should_flatten_query_param? ( key , value , params_for_location )
126+ flatten_nested_query_param ( normalized , key . to_s , value )
127+ else
128+ normalized [ key ] = value
129+ end
130+ end
131+
132+ normalized
133+ end
134+
135+ # @param [Array<OpenAPIParser::Schemas::Parameter>] params_for_location
136+ # @return [Boolean]
137+ def requires_query_param_flattening? ( params_for_location )
138+ params_for_location . any? { |param_def | param_def . style == 'deepObject' || param_def . name . include? ( '[' ) }
139+ end
140+
141+ # @param [String, Symbol] key
142+ # @param [Object] value
143+ # @param [Array<OpenAPIParser::Schemas::Parameter>] params_for_location
144+ # @return [Boolean]
145+ def should_flatten_query_param? ( key , value , params_for_location )
146+ return false unless value . is_a? ( Hash )
147+
148+ key_name = key . to_s
149+ params_for_location . any? do |param_def |
150+ param_def . name == key_name || param_def . name . start_with? ( "#{ key_name } [" )
151+ end
152+ end
153+
154+ # @param [Hash] result
155+ # @param [String] prefix
156+ # @param [Object] value
157+ # @return [void]
158+ def flatten_nested_query_param ( result , prefix , value )
159+ case value
160+ when Hash
161+ value . each do |child_key , child_value |
162+ flatten_nested_query_param ( result , "#{ prefix } [#{ child_key } ]" , child_value )
163+ end
164+ else
165+ result [ prefix ] = value
166+ end
167+ end
168+
108169 # Extract and deserialize a single parameter
109170 # @param [OpenAPIParser::Schemas::Parameter] param_def Parameter definition
110171 # @param [Hash] raw_params Raw parameters
0 commit comments