【问题标题】:How to convert URL parameters to a JavaScript object? [duplicate]如何将 URL 参数转换为 JavaScript 对象? [复制]
【发布时间】:2012-01-28 18:02:37
【问题描述】:

我有一个这样的字符串:

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

如何将它转换成这样的 JavaScript 对象?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}

【问题讨论】:

标签: javascript url url-parameters url-parsing


【解决方案1】:

/**
 * 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

【讨论】:

    【解决方案2】:

    这是silicakes' approach 的更精简版本。

    以下函数可以解析来自USVStringLocation 的查询字符串。

    /**
     * Returns a plain object representation of a URLSearchParams object.
     * @param {USVString} search - A URL querystring
     * @return {Object} a key-value pair object from a URL querystring
     */
    const parseSearch = (search) =>
      [...new URLSearchParams(search).entries()]
        .reduce((acc, [key, val]) => ({
          ...acc,
          // eslint-disable-next-line no-nested-ternary
          [key]: Object.prototype.hasOwnProperty.call(acc, key)
            ? Array.isArray(acc[key])
              ? [...acc[key], val]
              : [acc[key], val]
            : val
        }), {});
    
    /**
     * Returns a plain object representation of a URLSearchParams object.
     * @param {Location} location - Either a document or window location, or React useLocation()
     * @return {Object} a key-value pair object from a URL querystring
     */
    const parseLocationSearch = (location) => parseSearch(location.search);
    
    console.log(parseSearch('?foo=bar&x=y&ids=%5B1%2C2%2C3%5D&ids=%5B4%2C5%2C6%5D'));
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    这是上面代码的单行代码(125 字节):

    fparseSearch

    f=s=>[...new URLSearchParams(s).entries()].reduce((a,[k,v])=>({...a,[k]:a[k]?Array.isArray(a[k])?[...a[k],v]:[a[k],v]:v}),{})
    

    编辑

    这里是一个序列化和更新的方法:

    const parseSearch = (search) =>
      [...new URLSearchParams(search).entries()]
        .reduce((acc, [key, val]) => ({
          ...acc,
          // eslint-disable-next-line no-nested-ternary
          [key]: Object.prototype.hasOwnProperty.call(acc, key)
            ? Array.isArray(acc[key])
              ? [...acc[key], val]
              : [acc[key], val]
            : val
        }), {});
    
    const toQueryString = (params) =>
      `?${Object.entries(params)
        .flatMap(([key, values]) =>
          Array.isArray(values)
            ? values.map(value => [key, value])
            : [[key, values]])
        .map(pair => pair.map(val => encodeURIComponent(val)).join('='))
        .join('&')}`;
    
    const updateQueryString = (search, update) =>
      (parsed =>
        toQueryString(update instanceof Function
          ? update(parsed)
          : { ...parsed, ...update }))
      (parseSearch(search));
    
    const queryString = '?foo=bar&x=y&ids=%5B1%2C2%2C3%5D&ids=%5B4%2C5%2C6%5D';
    const parsedQuery = parseSearch(queryString);
    console.log(parsedQuery);
    console.log(toQueryString(parsedQuery) === queryString);
    
    const updatedQuerySimple = updateQueryString(queryString, {
      foo: 'baz',
      x: 'z',
    });
    console.log(updatedQuerySimple);
    console.log(parseSearch(updatedQuerySimple));
    
    const updatedQuery = updateQueryString(updatedQuerySimple, parsed => ({
      ...parsed,
      ids: [
        ...parsed.ids,
        JSON.stringify([7,8,9])
      ]
    }));
    console.log(updatedQuery);
    console.log(parseSearch(updatedQuery));
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    【讨论】:

      【解决方案3】:

      对于 ES6 有相当简单且不正确的答案:

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

      但是这一行代码不涵盖多个相同的键,你必须使用更复杂的东西:

      function parseParams(params) {
        const output = [];
        const searchParams = new URLSearchParams(params);
      
        // Set will return only unique keys()
        new Set([...searchParams.keys()])
          .forEach(key => {
            output[key] = searchParams.getAll(key).length > 1 ?  
              searchParams.getAll(key) : // get multiple values
              searchParams.get(key); // get single value
          });
      
        return output;
      }
      
      console.log(
         parseParams('abc=foo&cars=Ford&cars=BMW&cars=Skoda&cars=Mercedes')
      )
      

      代码将生成以下结构:

      [
        abc: "foo"
        cars: ["Ford", "BMW", "Skoda", "Mercedes"]
      ]
      

      【讨论】:

        【解决方案4】:

        许多其他解决方案不考虑极端情况。

        这个处理

        • 空键a=1&amp;b=2&amp;
        • 空值a=1&amp;b
        • 空值a=1&amp;b=
        • 未编码的等号a=1&amp;b=2=3=4
          decodeQueryString: qs => {
            // expects qs to not have a ?
            // return if empty qs
            if (qs === '') return {};
            return qs.split('&').reduce((acc, pair) => {
              // skip no param at all a=1&b=2&
              if (pair.length === 0) return acc;
              const parts = pair.split('=');
              // fix params without value
              if (parts.length === 1) parts[1] = '';
              // for value handle multiple unencoded = signs
              const key = decodeURIComponent(parts[0]);
              const value = decodeURIComponent(parts.slice(1).join('='));
              acc[key] = value;
              return acc;
            }, {});
          },
        

        【讨论】:

          猜你喜欢
          • 2014-05-05
          • 1970-01-01
          • 2015-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-18
          相关资源
          最近更新 更多