@@ -688,39 +688,51 @@ class RouteRecognizer<THandler = string> {
688688 }
689689
690690 generateQueryString ( params : Params ) : string {
691- const pairs : string [ ] = [ ] ;
692- const keys : string [ ] = Object . keys ( params ) ;
693- keys . sort ( ) ;
694- for ( let i = 0 ; i < keys . length ; i ++ ) {
695- const key = keys [ i ] ;
696- const value = params [ key ] ;
697- if ( value == null ) {
698- continue ;
691+ const reducer = ( obj : Params , parentPrefix : string | null = null ) => ( prev : string [ ] , key : string ) => {
692+ const val = obj [ key ] ;
693+ if ( val === null || val === undefined ) {
694+ return prev ;
699695 }
700- let pair = encodeURIComponent ( key ) ;
701- if ( isArray ( value ) ) {
702- for ( let j = 0 ; j < value . length ; j ++ ) {
703- const arrayPair = key + "[]" + "=" + encodeURIComponent ( value [ j ] ) ;
704- pairs . push ( arrayPair ) ;
705- }
706- } else {
707- pair += "=" + encodeURIComponent ( value as string ) ;
708- pairs . push ( pair ) ;
696+
697+ const prefix = parentPrefix ? `${ parentPrefix } [${ key } ]` : key ;
698+
699+ if ( val == null || typeof val === 'function' ) {
700+ prev . push ( `${ prefix } =` ) ;
701+ return prev ;
709702 }
710- }
703+
704+ if ( isArray ( val ) && val . every ( ( v ) => [ 'string' , 'number' , 'boolean' ] . includes ( typeof v ) ) ) {
705+ for ( let j = 0 ; j < val . length ; j ++ ) {
706+ // handle array query params. array format brackets. (Other options are indices a[0]=b&a[1]=c or repeat a=b&a=c)
707+ const arrayPair = key + "[]" + "=" + encodeURIComponent ( val [ j ] ) ;
708+ prev . push ( arrayPair ) ;
709+ }
711710
712- if ( pairs . length === 0 ) {
713- return "" ;
711+ return prev ;
712+ } else if ( [ 'string' , 'number' , 'boolean' ] . includes ( typeof val ) ) {
713+ prev . push ( `${ prefix } =${ encodeURIComponent ( val as string ) } ` ) ;
714+ return prev ;
715+ }
716+
717+ prev . push ( Object . keys ( val as Params ) . sort ( ) . reduce ( reducer ( val as Params , parentPrefix ? prefix : `${ prefix } =` ) , [ ] ) . join ( '&' ) ) ;
718+ return prev ;
719+ } ;
720+
721+ const sortedKeys = Object . keys ( params ) . sort ( ) ;
722+ // avoid appending unnecessary '?'
723+ if ( ! sortedKeys . length || sortedKeys . every ( ( k ) => params [ k ] === undefined || params [ k ] === null ) ) {
724+ return '' ;
714725 }
715726
716- return "?" + pairs . join ( "&" ) ;
727+ return '?' + sortedKeys . reduce ( reducer ( params ) , [ ] ) . join ( '&' ) ;
717728 }
718729
719730 parseQueryString ( queryString : string ) : QueryParams {
720731 const pairs = queryString . split ( "&" ) ;
721732 const queryParams : QueryParams = { } ;
722733 for ( let i = 0 ; i < pairs . length ; i ++ ) {
723734 const pair = pairs [ i ] . split ( "=" ) ;
735+ console . warn ( pair )
724736 let key = decodeQueryParamPart ( pair [ 0 ] ) ;
725737 const keyLength = key . length ;
726738 let isArray = false ;
0 commit comments