How to convert URL parameters to a JavaScript object?

前端 未结 30 1030
时光取名叫无心
时光取名叫无心 2020-11-22 13:57

I have a string like this:

abc=foo&def=%5Basf%5D&xyz=5

How can I convert it into a JavaScript object like this?

{
          


        
相关标签:
30条回答
  • 2020-11-22 14:36

    console.log(decodeURI('abc=foo&def=%5Basf%5D&xyz=5')
      .split('&')
      .reduce((result, current) => {
        const [key, value] = current.split('=');
    
        result[key] = value;
    
        return result
      }, {}))

    0 讨论(0)
  • 2020-11-22 14:37

    2020 ES6/7/8 and on approach

    Starting ES6 and on, Javascript offers several constructs in order to create a performant solution for this issue.

    This includes using URLSearchParams and iterators

    let params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
    params.get("abc"); // "foo"
    

    Should your use case requires you to actually convert it to object, you can implement the following function:

    function paramsToObject(entries) {
      const result = {}
      for(const [key, value] of entries) { // each 'entry' is a [key, value] tupple
        result[key] = value;
      }
      return result;
    }
    

    Basic Demo

    const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
    const entries = urlParams.entries(); //returns an iterator of decoded [key,value] tuples
    const params = paramsToObject(entries); //{abc:"foo",def:"[asf]",xyz:"5"}
    

    Using Object.fromEntries and spread

    We can use Object.fromEntries (which is currently in stage 4), replacing paramsToObject with Object.fromEntries(entries).

    The value pairs to iterate over are the list name-value pairs with the key being the name and the value being the value.

    Since URLParams, returns an iterable object, using the spread operator instead of calling .entries will also yield entries per its spec:

    const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
    const params = Object.fromEntries(urlParams); // {abc: "foo", def: "[asf]", xyz: "5"}
    

    Note: All values are automatically strings as per the URLSearchParams spec

    Multiple same keys

    As @siipe pointed out, strings containing multiple same-key values will be coerced into the last available value: foo=first_value&foo=second_value will in essence become: {foo: "second_value"}.

    As per this answer: https://stackoverflow.com/a/1746566/1194694 there's no spec for deciding what to do with it and each framework can behave differently.

    A common use case will be to join the two same values into an array, making the output object into:

    {foo: ["first_value", "second_value"]}
    

    This can be achieved with the following code:

    const groupParamsByKey = (params) => [...params.entries()].reduce((acc, tuple) => {
     // getting the key and value from each tuple
     const [key, val] = tuple;
     if(acc.hasOwnProperty(key)) {
        // if the current key is already an array, we'll add the value to it
        if(Array.isArray(acc[key])) {
          acc[key] = [...acc[key], val]
        } else {
          // if it's not an array, but contains a value, we'll convert it into an array
          // and add the current value to it
          acc[key] = [acc[key], val];
        }
     } else {
      // plain assignment if no special case is present
      acc[key] = val;
     }
    
    return acc;
    }, {});
    
    const params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5&def=dude');
    const output = groupParamsByKey(params) // {abc: "foo", def: ["[asf]", "dude"], xyz: 5}
    
    0 讨论(0)
  • 2020-11-22 14:39

    2019 One-Liner Approach

    For your specific case:

    Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'));
    

    For the more generic case where someone wants to parse query params to an object:

    Object.fromEntries(new URLSearchParams(location.search));
    

    If you're unable to use Object.fromEntries, this will also work:

    Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
    
    0 讨论(0)
  • 2020-11-22 14:39

    /**
     * Parses and builds Object of URL query string.
     * @param {string} query The URL query string.
     * @return {!Object<string, string>}
     */
    function parseQueryString(query) {
      if (!query) {
        return {};
      }
      return (/^[?#]/.test(query) ? query.slice(1) : query)
          .split('&')
          .reduce((params, param) => {
            const item = param.split('=');
            const key = decodeURIComponent(item[0] || '');
            const value = decodeURIComponent(item[1] || '');
            if (key) {
              params[key] = value;
            }
            return params;
          }, {});
    }
    
    console.log(parseQueryString('?v=MFa9pvnVe0w&ku=user&from=89&aw=1'))
    see log

    0 讨论(0)
  • 2020-11-22 14:40

    For Node JS, you can use the Node JS API querystring:

    const querystring = require('querystring');
    
    querystring.parse('abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar');
    // returns the object
    

    Documentation: https://nodejs.org/api/querystring.html

    0 讨论(0)
  • 2020-11-22 14:40

    Here's one I use:

    var params = {};
    window.location.search.substring(1).split('&').forEach(function(pair) {
      pair = pair.split('=');
      if (pair[1] !== undefined) {
        var key = decodeURIComponent(pair[0]),
            val = decodeURIComponent(pair[1]),
            val = val ? val.replace(/\++/g,' ').trim() : '';
    
        if (key.length === 0) {
          return;
        }
        if (params[key] === undefined) {
          params[key] = val;
        }
        else {
          if ("function" !== typeof params[key].push) {
            params[key] = [params[key]];
          }
          params[key].push(val);
        }
      }
    });
    console.log(params);
    

    Basic usage, eg.
    ?a=aa&b=bb
    Object {a: "aa", b: "bb"}

    Duplicate params, eg.
    ?a=aa&b=bb&c=cc&c=potato
    Object {a: "aa", b: "bb", c: ["cc","potato"]}

    Missing keys, eg.
    ?a=aa&b=bb&=cc
    Object {a: "aa", b: "bb"}

    Missing values, eg.
    ?a=aa&b=bb&c
    Object {a: "aa", b: "bb"}

    The above JSON/regex solutions throw a syntax error on this wacky url:
    ?a=aa&b=bb&c=&=dd&e
    Object {a: "aa", b: "bb", c: ""}

    0 讨论(0)
提交回复
热议问题