Creating and parsing query strings

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite
1












In a moment of boredom, I decided to write two methods, one of which would create a query string, while the other would parse it, the constraint I imposed on myself being that each method could not exceed one statement. The result is by no means something I'd ever consider using at work or in my personal projects, for that matter; my reason for posting this question is that I'd like to know how, given the constraint I set for myself, the code could be improved on? Like, what's the best code you could write to solve the problem at hand - creating and parsing a query string - without having the two methods constitute more than 2 statements? I'm sure you could do it in a much more elegant manner, and I'm looking forward to any feedback coming my way!



const createQueryString = input => encodeURI(`?$Object.keys(input).map(name 
=> `$name=$input[name]`).join('&')`);

const queryString = createQueryString(
name: 'Darrell',
age: '3 2',
nationality: 'Swedish'
);

console.log(queryString);

const parseQueryString = (input, obj = Object.create(null)) =>
decodeURI(input.slice(input.indexOf('?') + 1,
input.length)).split('&').map(entry => [
[entry.split('=')[0]],
[entry.split('=')[1]]
]).reduce((obj, query) => Object.assign(obj,
[query[0][0]]: query[1][0]
), );

const parsedQueryString = parseQueryString(queryString);

console.log(parsedQueryString);






share|improve this question



























    up vote
    3
    down vote

    favorite
    1












    In a moment of boredom, I decided to write two methods, one of which would create a query string, while the other would parse it, the constraint I imposed on myself being that each method could not exceed one statement. The result is by no means something I'd ever consider using at work or in my personal projects, for that matter; my reason for posting this question is that I'd like to know how, given the constraint I set for myself, the code could be improved on? Like, what's the best code you could write to solve the problem at hand - creating and parsing a query string - without having the two methods constitute more than 2 statements? I'm sure you could do it in a much more elegant manner, and I'm looking forward to any feedback coming my way!



    const createQueryString = input => encodeURI(`?$Object.keys(input).map(name 
    => `$name=$input[name]`).join('&')`);

    const queryString = createQueryString(
    name: 'Darrell',
    age: '3 2',
    nationality: 'Swedish'
    );

    console.log(queryString);

    const parseQueryString = (input, obj = Object.create(null)) =>
    decodeURI(input.slice(input.indexOf('?') + 1,
    input.length)).split('&').map(entry => [
    [entry.split('=')[0]],
    [entry.split('=')[1]]
    ]).reduce((obj, query) => Object.assign(obj,
    [query[0][0]]: query[1][0]
    ), );

    const parsedQueryString = parseQueryString(queryString);

    console.log(parsedQueryString);






    share|improve this question























      up vote
      3
      down vote

      favorite
      1









      up vote
      3
      down vote

      favorite
      1






      1





      In a moment of boredom, I decided to write two methods, one of which would create a query string, while the other would parse it, the constraint I imposed on myself being that each method could not exceed one statement. The result is by no means something I'd ever consider using at work or in my personal projects, for that matter; my reason for posting this question is that I'd like to know how, given the constraint I set for myself, the code could be improved on? Like, what's the best code you could write to solve the problem at hand - creating and parsing a query string - without having the two methods constitute more than 2 statements? I'm sure you could do it in a much more elegant manner, and I'm looking forward to any feedback coming my way!



      const createQueryString = input => encodeURI(`?$Object.keys(input).map(name 
      => `$name=$input[name]`).join('&')`);

      const queryString = createQueryString(
      name: 'Darrell',
      age: '3 2',
      nationality: 'Swedish'
      );

      console.log(queryString);

      const parseQueryString = (input, obj = Object.create(null)) =>
      decodeURI(input.slice(input.indexOf('?') + 1,
      input.length)).split('&').map(entry => [
      [entry.split('=')[0]],
      [entry.split('=')[1]]
      ]).reduce((obj, query) => Object.assign(obj,
      [query[0][0]]: query[1][0]
      ), );

      const parsedQueryString = parseQueryString(queryString);

      console.log(parsedQueryString);






      share|improve this question













      In a moment of boredom, I decided to write two methods, one of which would create a query string, while the other would parse it, the constraint I imposed on myself being that each method could not exceed one statement. The result is by no means something I'd ever consider using at work or in my personal projects, for that matter; my reason for posting this question is that I'd like to know how, given the constraint I set for myself, the code could be improved on? Like, what's the best code you could write to solve the problem at hand - creating and parsing a query string - without having the two methods constitute more than 2 statements? I'm sure you could do it in a much more elegant manner, and I'm looking forward to any feedback coming my way!



      const createQueryString = input => encodeURI(`?$Object.keys(input).map(name 
      => `$name=$input[name]`).join('&')`);

      const queryString = createQueryString(
      name: 'Darrell',
      age: '3 2',
      nationality: 'Swedish'
      );

      console.log(queryString);

      const parseQueryString = (input, obj = Object.create(null)) =>
      decodeURI(input.slice(input.indexOf('?') + 1,
      input.length)).split('&').map(entry => [
      [entry.split('=')[0]],
      [entry.split('=')[1]]
      ]).reduce((obj, query) => Object.assign(obj,
      [query[0][0]]: query[1][0]
      ), );

      const parsedQueryString = parseQueryString(queryString);

      console.log(parsedQueryString);








      share|improve this question












      share|improve this question




      share|improve this question








      edited Feb 9 at 21:36









      200_success

      123k14143401




      123k14143401









      asked Feb 8 at 20:54









      Happy Koala

      20218




      20218




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          Well this is a fascinating question!



          I don't see much you could do in createQueryString besides potentially using Object.entries instead of Object.keys and a slight rearrangement to get rid of the outer template string.



          const createQueryString = input => 
          '?' + encodeURI(Object.entries(input)
          .map(([name, value]) => `$name=$value`).join('&'));


          Do note that there is a problem here if your name or value contains &. To fix this you would need to call encodeURIComponent on each part and then drop the outer enocdeURI call.



          const createQueryString = input => 
          '?' + Object.entries(input)
          .map(([name, value]) =>
          `$encodeURIComponent(name)=$encodeURIComponent(value)`
          ).join('&');


          parseQueryString can be improved in several ways.



          1. You don't use obj = Object.create(null), so get rid of it.


          2. There is a (mostly) a built in way to do this which I will pretend doesn't exist for the rest of this post. (One disadvantage with this method is that it requires a full URI, not just the query string)



            [...new URL(uri).searchParams.entries()]
            .reduce((obj, entry) => Object.assign(obj, [entry[0]]: entry[1] ), )



          3. You can use regular expressions to simplify the code slightly.



            const parseQueryString = (input) => 
            input.slice(input.indexOf('?') + 1)
            .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
            .map(s => s.split('=').map(decodeURIComponent))
            .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )


          Full demo:






          const createQueryString = input => 
          '?' + Object.entries(input)
          .map(([name, value]) =>
          `$encodeURIComponent(name)=$encodeURIComponent(value)`
          ).join('&');

          const queryString = createQueryString(
          name: 'Darrell',
          age: '3 2',
          nationality: 'Swedish',
          messy: '&hi=bye'
          );

          const parseQueryString = input =>
          input.slice(input.indexOf('?') + 1)
          .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
          .map(s => s.split('=').map(decodeURIComponent))
          .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

          const parsedQueryString = parseQueryString(queryString);

          console.log(parsedQueryString)








          share|improve this answer




























            up vote
            2
            down vote













            Everyone went through the unnecessary effort of building a parser/generator when modern browsers like Firefox, Chrome and Safari have URLSearchParams. Here it is, wrapped in the functions mentioned:






            const createQueryString = i => (new URLSearchParams(i)).toString()
            const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

            const queryString = createQueryString(
            name: 'Darrell',
            age: '3 2',
            nationality: 'Swedish'
            );

            console.log(queryString);

            const parsedQueryString = parseQueryString(queryString);

            console.log(parsedQueryString);





            Of course, your mileage may vary. If you want to support legacy browsers, you can just polyfill. That way, your code is forward-looking, and removing legacy support would only mean removing the polyfill, not updating the code.






            share|improve this answer





















            • Not sure how I missed that you could just use URLSearchParams. Good catch!
              – Gerrit0
              Feb 9 at 20:30

















            up vote
            0
            down vote













            A good problem for regExp and string methods. Though I would not consider that a single expression can have a comma. (a,b) is two expressions in my book, which would mean only one argument per function call, one entry per array. Without the comma its near impossible?



            The followings is an example of how you should not write code.



            e encoding function.
            p parsing function.



            e=i=>encodeURI("?"+Object.entries(i).join('&').replace(/((^|&).*?),/g,"$1="))
            p=(i,o=)=>((decodeURI(i)+"&").replace(/([^?].*?)=(.*?)&/g,(p,a,b)=>o[a]=b),o)

            const queryString = e(name: "Blind",age: "5 0",nationality: 'Australian')
            const parsedString = p(queryString);


            AS pointed out by Joseph answer URLSearchParams is a perfect, but his answer was a little bloated and can be simplified



            The is no need for the toString() as it can be coerced with an empty string



            const createQueryString =i=>""+new URLSearchParams(i)


            And the parse can be simplified removing the redundant entries call and creating an array literal populated via a spread operator.



            const parseQStr = (i,o=)=>([...new URLSearchParams(i)].forEach(v=>o[v[0]]=v[1]),o)

            // or the slightly slower
            const parseQStr = i=>[...new URLSearchParams(i)].reduce((o,v)=>(o[v[0]]=v[1]),o),)





            share|improve this answer























            • Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
              – Gerrit0
              Feb 9 at 17:42










            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187122%2fcreating-and-parsing-query-strings%23new-answer', 'question_page');

            );

            Post as a guest






























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote



            accepted










            Well this is a fascinating question!



            I don't see much you could do in createQueryString besides potentially using Object.entries instead of Object.keys and a slight rearrangement to get rid of the outer template string.



            const createQueryString = input => 
            '?' + encodeURI(Object.entries(input)
            .map(([name, value]) => `$name=$value`).join('&'));


            Do note that there is a problem here if your name or value contains &. To fix this you would need to call encodeURIComponent on each part and then drop the outer enocdeURI call.



            const createQueryString = input => 
            '?' + Object.entries(input)
            .map(([name, value]) =>
            `$encodeURIComponent(name)=$encodeURIComponent(value)`
            ).join('&');


            parseQueryString can be improved in several ways.



            1. You don't use obj = Object.create(null), so get rid of it.


            2. There is a (mostly) a built in way to do this which I will pretend doesn't exist for the rest of this post. (One disadvantage with this method is that it requires a full URI, not just the query string)



              [...new URL(uri).searchParams.entries()]
              .reduce((obj, entry) => Object.assign(obj, [entry[0]]: entry[1] ), )



            3. You can use regular expressions to simplify the code slightly.



              const parseQueryString = (input) => 
              input.slice(input.indexOf('?') + 1)
              .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
              .map(s => s.split('=').map(decodeURIComponent))
              .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )


            Full demo:






            const createQueryString = input => 
            '?' + Object.entries(input)
            .map(([name, value]) =>
            `$encodeURIComponent(name)=$encodeURIComponent(value)`
            ).join('&');

            const queryString = createQueryString(
            name: 'Darrell',
            age: '3 2',
            nationality: 'Swedish',
            messy: '&hi=bye'
            );

            const parseQueryString = input =>
            input.slice(input.indexOf('?') + 1)
            .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
            .map(s => s.split('=').map(decodeURIComponent))
            .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

            const parsedQueryString = parseQueryString(queryString);

            console.log(parsedQueryString)








            share|improve this answer

























              up vote
              2
              down vote



              accepted










              Well this is a fascinating question!



              I don't see much you could do in createQueryString besides potentially using Object.entries instead of Object.keys and a slight rearrangement to get rid of the outer template string.



              const createQueryString = input => 
              '?' + encodeURI(Object.entries(input)
              .map(([name, value]) => `$name=$value`).join('&'));


              Do note that there is a problem here if your name or value contains &. To fix this you would need to call encodeURIComponent on each part and then drop the outer enocdeURI call.



              const createQueryString = input => 
              '?' + Object.entries(input)
              .map(([name, value]) =>
              `$encodeURIComponent(name)=$encodeURIComponent(value)`
              ).join('&');


              parseQueryString can be improved in several ways.



              1. You don't use obj = Object.create(null), so get rid of it.


              2. There is a (mostly) a built in way to do this which I will pretend doesn't exist for the rest of this post. (One disadvantage with this method is that it requires a full URI, not just the query string)



                [...new URL(uri).searchParams.entries()]
                .reduce((obj, entry) => Object.assign(obj, [entry[0]]: entry[1] ), )



              3. You can use regular expressions to simplify the code slightly.



                const parseQueryString = (input) => 
                input.slice(input.indexOf('?') + 1)
                .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                .map(s => s.split('=').map(decodeURIComponent))
                .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )


              Full demo:






              const createQueryString = input => 
              '?' + Object.entries(input)
              .map(([name, value]) =>
              `$encodeURIComponent(name)=$encodeURIComponent(value)`
              ).join('&');

              const queryString = createQueryString(
              name: 'Darrell',
              age: '3 2',
              nationality: 'Swedish',
              messy: '&hi=bye'
              );

              const parseQueryString = input =>
              input.slice(input.indexOf('?') + 1)
              .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
              .map(s => s.split('=').map(decodeURIComponent))
              .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

              const parsedQueryString = parseQueryString(queryString);

              console.log(parsedQueryString)








              share|improve this answer























                up vote
                2
                down vote



                accepted







                up vote
                2
                down vote



                accepted






                Well this is a fascinating question!



                I don't see much you could do in createQueryString besides potentially using Object.entries instead of Object.keys and a slight rearrangement to get rid of the outer template string.



                const createQueryString = input => 
                '?' + encodeURI(Object.entries(input)
                .map(([name, value]) => `$name=$value`).join('&'));


                Do note that there is a problem here if your name or value contains &. To fix this you would need to call encodeURIComponent on each part and then drop the outer enocdeURI call.



                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');


                parseQueryString can be improved in several ways.



                1. You don't use obj = Object.create(null), so get rid of it.


                2. There is a (mostly) a built in way to do this which I will pretend doesn't exist for the rest of this post. (One disadvantage with this method is that it requires a full URI, not just the query string)



                  [...new URL(uri).searchParams.entries()]
                  .reduce((obj, entry) => Object.assign(obj, [entry[0]]: entry[1] ), )



                3. You can use regular expressions to simplify the code slightly.



                  const parseQueryString = (input) => 
                  input.slice(input.indexOf('?') + 1)
                  .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                  .map(s => s.split('=').map(decodeURIComponent))
                  .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )


                Full demo:






                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');

                const queryString = createQueryString(
                name: 'Darrell',
                age: '3 2',
                nationality: 'Swedish',
                messy: '&hi=bye'
                );

                const parseQueryString = input =>
                input.slice(input.indexOf('?') + 1)
                .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                .map(s => s.split('=').map(decodeURIComponent))
                .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

                const parsedQueryString = parseQueryString(queryString);

                console.log(parsedQueryString)








                share|improve this answer













                Well this is a fascinating question!



                I don't see much you could do in createQueryString besides potentially using Object.entries instead of Object.keys and a slight rearrangement to get rid of the outer template string.



                const createQueryString = input => 
                '?' + encodeURI(Object.entries(input)
                .map(([name, value]) => `$name=$value`).join('&'));


                Do note that there is a problem here if your name or value contains &. To fix this you would need to call encodeURIComponent on each part and then drop the outer enocdeURI call.



                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');


                parseQueryString can be improved in several ways.



                1. You don't use obj = Object.create(null), so get rid of it.


                2. There is a (mostly) a built in way to do this which I will pretend doesn't exist for the rest of this post. (One disadvantage with this method is that it requires a full URI, not just the query string)



                  [...new URL(uri).searchParams.entries()]
                  .reduce((obj, entry) => Object.assign(obj, [entry[0]]: entry[1] ), )



                3. You can use regular expressions to simplify the code slightly.



                  const parseQueryString = (input) => 
                  input.slice(input.indexOf('?') + 1)
                  .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                  .map(s => s.split('=').map(decodeURIComponent))
                  .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )


                Full demo:






                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');

                const queryString = createQueryString(
                name: 'Darrell',
                age: '3 2',
                nationality: 'Swedish',
                messy: '&hi=bye'
                );

                const parseQueryString = input =>
                input.slice(input.indexOf('?') + 1)
                .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                .map(s => s.split('=').map(decodeURIComponent))
                .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

                const parsedQueryString = parseQueryString(queryString);

                console.log(parsedQueryString)








                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');

                const queryString = createQueryString(
                name: 'Darrell',
                age: '3 2',
                nationality: 'Swedish',
                messy: '&hi=bye'
                );

                const parseQueryString = input =>
                input.slice(input.indexOf('?') + 1)
                .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                .map(s => s.split('=').map(decodeURIComponent))
                .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

                const parsedQueryString = parseQueryString(queryString);

                console.log(parsedQueryString)





                const createQueryString = input => 
                '?' + Object.entries(input)
                .map(([name, value]) =>
                `$encodeURIComponent(name)=$encodeURIComponent(value)`
                ).join('&');

                const queryString = createQueryString(
                name: 'Darrell',
                age: '3 2',
                nationality: 'Swedish',
                messy: '&hi=bye'
                );

                const parseQueryString = input =>
                input.slice(input.indexOf('?') + 1)
                .match(/[wd%-!.~'()*]+=[wd%-!.~'()*]+/g)
                .map(s => s.split('=').map(decodeURIComponent))
                .reduce((obj, [key, value]) => Object.assign(obj, [key]: value ), )

                const parsedQueryString = parseQueryString(queryString);

                console.log(parsedQueryString)






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered Feb 8 at 22:16









                Gerrit0

                2,6701518




                2,6701518






















                    up vote
                    2
                    down vote













                    Everyone went through the unnecessary effort of building a parser/generator when modern browsers like Firefox, Chrome and Safari have URLSearchParams. Here it is, wrapped in the functions mentioned:






                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);





                    Of course, your mileage may vary. If you want to support legacy browsers, you can just polyfill. That way, your code is forward-looking, and removing legacy support would only mean removing the polyfill, not updating the code.






                    share|improve this answer





















                    • Not sure how I missed that you could just use URLSearchParams. Good catch!
                      – Gerrit0
                      Feb 9 at 20:30














                    up vote
                    2
                    down vote













                    Everyone went through the unnecessary effort of building a parser/generator when modern browsers like Firefox, Chrome and Safari have URLSearchParams. Here it is, wrapped in the functions mentioned:






                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);





                    Of course, your mileage may vary. If you want to support legacy browsers, you can just polyfill. That way, your code is forward-looking, and removing legacy support would only mean removing the polyfill, not updating the code.






                    share|improve this answer





















                    • Not sure how I missed that you could just use URLSearchParams. Good catch!
                      – Gerrit0
                      Feb 9 at 20:30












                    up vote
                    2
                    down vote










                    up vote
                    2
                    down vote









                    Everyone went through the unnecessary effort of building a parser/generator when modern browsers like Firefox, Chrome and Safari have URLSearchParams. Here it is, wrapped in the functions mentioned:






                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);





                    Of course, your mileage may vary. If you want to support legacy browsers, you can just polyfill. That way, your code is forward-looking, and removing legacy support would only mean removing the polyfill, not updating the code.






                    share|improve this answer













                    Everyone went through the unnecessary effort of building a parser/generator when modern browsers like Firefox, Chrome and Safari have URLSearchParams. Here it is, wrapped in the functions mentioned:






                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);





                    Of course, your mileage may vary. If you want to support legacy browsers, you can just polyfill. That way, your code is forward-looking, and removing legacy support would only mean removing the polyfill, not updating the code.






                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);





                    const createQueryString = i => (new URLSearchParams(i)).toString()
                    const parseQueryString = i => Array.from(new URLSearchParams(i).entries()).reduce((c, p) => (c[p[0]] = p[1], c), )

                    const queryString = createQueryString(
                    name: 'Darrell',
                    age: '3 2',
                    nationality: 'Swedish'
                    );

                    console.log(queryString);

                    const parsedQueryString = parseQueryString(queryString);

                    console.log(parsedQueryString);






                    share|improve this answer













                    share|improve this answer



                    share|improve this answer











                    answered Feb 9 at 18:11









                    Joseph

                    22.1k21833




                    22.1k21833











                    • Not sure how I missed that you could just use URLSearchParams. Good catch!
                      – Gerrit0
                      Feb 9 at 20:30
















                    • Not sure how I missed that you could just use URLSearchParams. Good catch!
                      – Gerrit0
                      Feb 9 at 20:30















                    Not sure how I missed that you could just use URLSearchParams. Good catch!
                    – Gerrit0
                    Feb 9 at 20:30




                    Not sure how I missed that you could just use URLSearchParams. Good catch!
                    – Gerrit0
                    Feb 9 at 20:30










                    up vote
                    0
                    down vote













                    A good problem for regExp and string methods. Though I would not consider that a single expression can have a comma. (a,b) is two expressions in my book, which would mean only one argument per function call, one entry per array. Without the comma its near impossible?



                    The followings is an example of how you should not write code.



                    e encoding function.
                    p parsing function.



                    e=i=>encodeURI("?"+Object.entries(i).join('&').replace(/((^|&).*?),/g,"$1="))
                    p=(i,o=)=>((decodeURI(i)+"&").replace(/([^?].*?)=(.*?)&/g,(p,a,b)=>o[a]=b),o)

                    const queryString = e(name: "Blind",age: "5 0",nationality: 'Australian')
                    const parsedString = p(queryString);


                    AS pointed out by Joseph answer URLSearchParams is a perfect, but his answer was a little bloated and can be simplified



                    The is no need for the toString() as it can be coerced with an empty string



                    const createQueryString =i=>""+new URLSearchParams(i)


                    And the parse can be simplified removing the redundant entries call and creating an array literal populated via a spread operator.



                    const parseQStr = (i,o=)=>([...new URLSearchParams(i)].forEach(v=>o[v[0]]=v[1]),o)

                    // or the slightly slower
                    const parseQStr = i=>[...new URLSearchParams(i)].reduce((o,v)=>(o[v[0]]=v[1]),o),)





                    share|improve this answer























                    • Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                      – Gerrit0
                      Feb 9 at 17:42














                    up vote
                    0
                    down vote













                    A good problem for regExp and string methods. Though I would not consider that a single expression can have a comma. (a,b) is two expressions in my book, which would mean only one argument per function call, one entry per array. Without the comma its near impossible?



                    The followings is an example of how you should not write code.



                    e encoding function.
                    p parsing function.



                    e=i=>encodeURI("?"+Object.entries(i).join('&').replace(/((^|&).*?),/g,"$1="))
                    p=(i,o=)=>((decodeURI(i)+"&").replace(/([^?].*?)=(.*?)&/g,(p,a,b)=>o[a]=b),o)

                    const queryString = e(name: "Blind",age: "5 0",nationality: 'Australian')
                    const parsedString = p(queryString);


                    AS pointed out by Joseph answer URLSearchParams is a perfect, but his answer was a little bloated and can be simplified



                    The is no need for the toString() as it can be coerced with an empty string



                    const createQueryString =i=>""+new URLSearchParams(i)


                    And the parse can be simplified removing the redundant entries call and creating an array literal populated via a spread operator.



                    const parseQStr = (i,o=)=>([...new URLSearchParams(i)].forEach(v=>o[v[0]]=v[1]),o)

                    // or the slightly slower
                    const parseQStr = i=>[...new URLSearchParams(i)].reduce((o,v)=>(o[v[0]]=v[1]),o),)





                    share|improve this answer























                    • Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                      – Gerrit0
                      Feb 9 at 17:42












                    up vote
                    0
                    down vote










                    up vote
                    0
                    down vote









                    A good problem for regExp and string methods. Though I would not consider that a single expression can have a comma. (a,b) is two expressions in my book, which would mean only one argument per function call, one entry per array. Without the comma its near impossible?



                    The followings is an example of how you should not write code.



                    e encoding function.
                    p parsing function.



                    e=i=>encodeURI("?"+Object.entries(i).join('&').replace(/((^|&).*?),/g,"$1="))
                    p=(i,o=)=>((decodeURI(i)+"&").replace(/([^?].*?)=(.*?)&/g,(p,a,b)=>o[a]=b),o)

                    const queryString = e(name: "Blind",age: "5 0",nationality: 'Australian')
                    const parsedString = p(queryString);


                    AS pointed out by Joseph answer URLSearchParams is a perfect, but his answer was a little bloated and can be simplified



                    The is no need for the toString() as it can be coerced with an empty string



                    const createQueryString =i=>""+new URLSearchParams(i)


                    And the parse can be simplified removing the redundant entries call and creating an array literal populated via a spread operator.



                    const parseQStr = (i,o=)=>([...new URLSearchParams(i)].forEach(v=>o[v[0]]=v[1]),o)

                    // or the slightly slower
                    const parseQStr = i=>[...new URLSearchParams(i)].reduce((o,v)=>(o[v[0]]=v[1]),o),)





                    share|improve this answer















                    A good problem for regExp and string methods. Though I would not consider that a single expression can have a comma. (a,b) is two expressions in my book, which would mean only one argument per function call, one entry per array. Without the comma its near impossible?



                    The followings is an example of how you should not write code.



                    e encoding function.
                    p parsing function.



                    e=i=>encodeURI("?"+Object.entries(i).join('&').replace(/((^|&).*?),/g,"$1="))
                    p=(i,o=)=>((decodeURI(i)+"&").replace(/([^?].*?)=(.*?)&/g,(p,a,b)=>o[a]=b),o)

                    const queryString = e(name: "Blind",age: "5 0",nationality: 'Australian')
                    const parsedString = p(queryString);


                    AS pointed out by Joseph answer URLSearchParams is a perfect, but his answer was a little bloated and can be simplified



                    The is no need for the toString() as it can be coerced with an empty string



                    const createQueryString =i=>""+new URLSearchParams(i)


                    And the parse can be simplified removing the redundant entries call and creating an array literal populated via a spread operator.



                    const parseQStr = (i,o=)=>([...new URLSearchParams(i)].forEach(v=>o[v[0]]=v[1]),o)

                    // or the slightly slower
                    const parseQStr = i=>[...new URLSearchParams(i)].reduce((o,v)=>(o[v[0]]=v[1]),o),)






                    share|improve this answer















                    share|improve this answer



                    share|improve this answer








                    edited Feb 10 at 7:10


























                    answered Feb 9 at 13:54









                    Blindman67

                    5,3701320




                    5,3701320











                    • Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                      – Gerrit0
                      Feb 9 at 17:42
















                    • Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                      – Gerrit0
                      Feb 9 at 17:42















                    Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                    – Gerrit0
                    Feb 9 at 17:42




                    Your queryString output is not correct. You shouldn't encode the leading ?, or the separating & and =. Since you encode everything there is no difference as far as your parser can tell between e(fails: '1&test=1') and e(fails: '1', test: '1').
                    – Gerrit0
                    Feb 9 at 17:42












                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187122%2fcreating-and-parsing-query-strings%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation