@@ -41,6 +41,7 @@ var paramReactorType = reflect.TypeFor[ParamReactor]()
4141var paramWrapperType = reflect .TypeFor [ParamWrapper ]()
4242var stringType = reflect .TypeFor [string ]()
4343var stringSliceType = reflect .TypeFor [[]string ]()
44+ var urlValuesType = reflect .TypeFor [url.Values ]()
4445
4546// Store int to string status number conversions for efficiency.
4647var statusStrings = map [int ]string {
@@ -862,7 +863,28 @@ func Register[I, O any](api API, op Operation, handler func(context.Context, *I)
862863
863864 var pv any
864865 var isSet bool
865- if p .Loc == "query" && p .Style == styleDeepObject {
866+ if p .Loc == "query" && p .Explode {
867+ // Exploded query parameters is a special case where we store the entire
868+ // map of query parameters.
869+ if p .Type != urlValuesType && p .Type != reflect .TypeFor [map [string ][]string ]() {
870+ panic ("unsupported exploded query param type " + p .Type .String ())
871+ }
872+ u := ctx .URL ()
873+ value := u .Query ()
874+ isSet = len (value ) > 0
875+ if len (value ) == 0 {
876+ if ! op .SkipValidateParams && p .Required {
877+ res .Add (pb , "" , "required " + p .Loc + " parameter is missing" )
878+ }
879+ return
880+ }
881+ anyMap := make (map [string ]any , len (value ))
882+ for k , v := range value {
883+ anyMap [k ] = v
884+ }
885+ pv = anyMap
886+ receiver .Set (reflect .ValueOf (value ))
887+ } else if p .Loc == "query" && p .Style == styleDeepObject {
866888 // Deep object style is a special case where we need to parse the
867889 // query parameter into a struct. We do this by parsing the query
868890 // parameter into a map, then iterating over the map and setting
0 commit comments