【问题标题】:Remove brackets from url with array of ids (Request.js)从带有 id 数组的 url 中删除括号(Request.js)
【发布时间】:2014-08-26 20:48:54
【问题描述】:

我有一个带有 nodejs express 的应用程序,它发出请求,但是当我传递一个数组时,我是:

例如:/foo?id=1&id=3&id=5

如何删除'[]'?

var requestQueryParams = {id: [1,3,5]}

var options = {
        url: 'www.test.com',
        headers: {'content-type': 'application/json', 'accept': 'application/json'},
        qs: requestQueryParams || {}
    };

request.get(options), function(){...}

结果:www.test.com?id[0]=1&id[1]=3&id[2]=5

Request.js = https://www.npmjs.org/package/request

Qs.js = https://www.npmjs.org/package/qs

Qs.stringify({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d'

【问题讨论】:

    标签: javascript node.js rest express request


    【解决方案1】:

    现在有一个更好的解决方案。 request 默认使用 qs 对传入的 qs 对象进行字符串化,该对象也接受格式化选项。其中一个选项是arrayFormat,它接受以下值:

    • indices:默认行为。生成一个包含索引的字符串:id[0]=foo&id[1]=bar&id[2]=baz。如果您想确保正确的顺序,这很有用。
    • brackets:生成一个仅附加括号的字符串:id[]=foo&id[]=bar&id[]=baz
    • repeat:生成不带任何括号的字符串:id=foo&id=bar&id=baz。不支持数组的旧服务可能会接受这一点,但只会使用最后一个值。

    带有 this 的选项对象如下所示:

    const request = require('request');
    const options = { 
      ...
      qs: {
        id: [ 'foo', 'bar', 'baz' ],
      },
      qsStringifyOptions: { arrayFormat: 'repeat' },
    };
    request(options);
    

    另请参阅https://github.com/request/request#requestoptions-callback,其中也提到了该选项。

    【讨论】:

      【解决方案2】:

      你想要什么?如果你想要www.test.com?id0=1&id1=3&id2=5,那么你需要给它一个这样的params对象:

      var requestQueryParams = { id0: 1, id1: 3, id2: 5 }
      

      如果您已经有一个看起来像{ id: [1,2,3] } 的对象,那么您需要将该对象转换为上述对象。你可以很容易地在for 循环中做到这一点:

      var requestQueryParams = { id: [1,3,5] },
          newRequestQueryParams = {};
      
      for(var i = 0; i < requestQueryParams.id.length; i++) {
        var paramName = "id" + i, // "id0", "id1", etc.
            id = requestQueryParams.id[i];
      
        newRequestQueryParams[paramName] = id;
      }
      
      console.log(newRequestQueryParams);
      // => { id0: 1, id1: 3, id2: 5 }
      

      更新:如果你想要一个像 id=1&amp;id=3&amp;id=5 这样的查询字符串(虽然这会很奇怪,正如我在下面的评论中提到的那样),你也可以在 for 循环中进行,如上所述,或者您可以执行以下操作:

      var requestQueryParams = { id: [1,3,5] },
          queryStringParts = [], // an array this time
          queryString;
      
      for(var i = 0; i < requestQueryParams.id.length; i++) {
        var param = "id=" + parseInt( requestQueryParams.id[i] );
        queryStringParts.push(param);
      }
      // queryStringParts is now [ "id=1", "id=3", "id=5" ]
      
      queryString = queryStringParts.join("&")
      console.log(queryString);
      // => "id=1&id=3&id=5"
      

      我在 for 循环中使用了 parseInt,因为我假设 ID 来自不受信任的来源(例如用户),并且因为您是手动构建字符串而不是使用将编码的库为您的数据,您希望防止恶意用户将任意字符串注入您的请求。您也可以使用encodeURIComponent,但如果 ID 应该始终是数字,那就有点过头了。

      【讨论】:

      • 我想要索引。
      • 在哪里你想“拥有索引”?我看到你编辑了你的问题,不幸的是,这使得它不太清楚。 id=1&amp;id=3&amp;id=5 是您想要结束的查询字符串吗?由于它是一种非常非标准的格式(使用重复的参数,大多数端点将只采用最后一个,即id=1id=3 将被忽略而有利于id=5),因此您可能只需要构建字符串手动。我将更新我的答案,以展示您如何做到这一点。
      • @JordanRunning:传递多个同名参数是传递值列表的标准方式。在查询字符串和 POST 数据中。每个 Web 框架都应该支持获取所有值。
      • 这很有趣,马蒂。你能给我一个标准的链接吗?
      【解决方案3】:

      我的解决方案被覆盖 (request.Request.prototype.qs)

      var qs = require('qs'),
      request = require('request'),
      url = require('url');
      
      var stringify;
      var toString = Object.prototype.toString;
      
      var isArray = Array.isArray || function (arr) {
      return toString.call(arr) === '[object Array]';
      };
      
      var objectKeys = Object.keys || function (obj) {
      var ret = [];
      for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
              ret.push(key);
          }
      }
      return ret;
      };
      
      var stringifyString = function (str, prefix) {
      if (!prefix) throw new TypeError('stringify expects an object');
      return prefix + '=' + encodeURIComponent(str);
      };
      
      var stringifyArray = function (arr, prefix) {
      var ret = [];
      if (!prefix) throw new TypeError('stringify expects an object');
      for (var i = 0; i < arr.length; i++) {
          ret.push(stringify(arr[i], prefix));
      }
      return ret.join('&');
      };
      
      function stringifyObject(obj, prefix) {
      var ret = [];
      var keys = objectKeys(obj);
      var key;
      
      for (var i = 0, len = keys.length; i < len; ++i) {
      
          key = keys[i];
      
          if ('' === key) {
              continue;
          }
      
          if (null === obj[key]) {
              ret.push(encodeURIComponent(key) + '=');
      
          } else {
              ret.push(stringify(obj[key], prefix ? prefix + '[' + encodeURIComponent(key) + ']' :     encodeURIComponent(key)));
          }
      }
      
      return ret.join('&');
      }
      
      stringify = function (obj, prefix) {
      if (isArray(obj)) {
          return stringifyArray(obj, prefix);
      } else if ('[object Object]' === toString.call(obj)) {
          return stringifyObject(obj, prefix);
      } else if ('string' === typeof obj) {
          return stringifyString(obj, prefix);
      } else {
          return prefix + '=' + encodeURIComponent(String(obj));
      }
      };
      

      并覆盖prototype.qs:

      request.Request.prototype.qs = function (q, clobber) {
      var base;
      
      if (!clobber && this.uri.query) {
          base = qs.parse(this.uri.query)
      }
      else {
          base = {}
      }
      
      for (var i in q) {
          base[i] = q[i]
      }
      
      if (stringify(base) === '') {
          return this
      }
      
      this.uri = url.parse(this.uri.href.split('?')[0] + '?' + stringify(base));
      this.url = this.uri;
      this.path = this.uri.path;
      
      return this;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-29
        • 2018-01-13
        • 2014-01-28
        • 1970-01-01
        • 2019-12-30
        • 1970-01-01
        • 2022-10-13
        • 1970-01-01
        相关资源
        最近更新 更多