【问题标题】:Node.js - Array is converted to object when sent in HTTP GET request queryNode.js - 在 HTTP GET 请求查询中发送时数组被转换为对象
【发布时间】:2017-11-26 09:18:57
【问题描述】:

以下 Node.js 代码:

var request = require('request');

var getLibs = function() {
    var options = { packages: ['example1', 'example2', 'example3'], os: 'linux', pack_type: 'npm' }

    request({url:'http://localhost:3000/package', qs:options}, 
    function (error , response, body) {
        if (! error && response.statusCode == 200) {
            console.log(body);
        } else if (error) {
            console.log(error);
        } else{
            console.log(response.statusCode);
        }
    });
}();

发送如下接收到的 http GET 请求查询:

{"packages"=>{"0"=>"example1", "1"=>"example2", "2"=>"example3"}, "os"=>"linux", "pack_type"=>"npm"}

我怎样才能优化这个请求,像这样接收:

{"packages"=>["example1", "example2", "example3"], "os"=>"linux", "pack_type"=>"npm"}

注意。 REST API 是在 Ruby on Rails 中构建的

【问题讨论】:

  • 我认为这是预期的行为。您将如何通过查询参数中的 get 请求实现发送数组?通常以?id[]=uuid1&id[]=uuid2 的形式发送
  • 我已经成功地使用 Ruby 以所需格式发送查询。那么为什么 Ruby 和 Node.js 之间的请求格式会发生变化呢?以及如何阻止它发生?

标签: ruby-on-rails node.js http get


【解决方案1】:

如果需要按原样接收数组,可以将useQuerystring设置为true

更新:以下代码示例中的list键已更改为'list[]',以便OP的ruby后端可以成功解析数组。

这里是示例代码:

const request = require('request');

let data = {
  'name': 'John',
  'list[]': ['XXX', 'YYY', 'ZZZ']
};

request({
  url: 'https://requestb.in/1fg1v0i1',
  qs: data,
  useQuerystring: true
}, function(err, res, body) {
  // ...
});

这样,当发送 HTTP GET 请求时,查询参数为:

?name=John&list[]=XXX&list[]=YYY&list[]=ZZZ

list 字段将被解析为['XXX', 'YYY', 'ZZZ']


没有useQuerystring(默认值为false),查询参数为:

?name=John&list[][0]=XXX&list[][1]=YYY&list[][2]=ZZZ

【讨论】:

  • 收到的查询就像您提到的那样:?packages=example1&packages=example2&packages=example3..... 但未解析为数组。相反,它变成了 {"packages"=>"uuid", "os"=>"linux", "pack_type"=>"npm"}
  • 我的 Ruby 代码中的查询被发送为:?packages[]=example1&packages[]=example2&packages[]=example3..... 然后解析为:{packages = ['example1', '示例2','示例3'],......}
  • @TamerB 然后你可以使用packages[]作为数据的key。我已经编辑了答案。
  • 这会将“包”作为一个包含一个对象的数组发送。即请求将是这样的:{"packages"=>[{"0"=>"example1","1"=>​​"example2","2"=>"example3"}]....}。无论如何,我终于找到了一个解决我问题的想法。请找到我的答案。谢谢你的努力:)
  • 谢谢@TamerB,但我有点困惑。您在 Ruby 代码(有效)中提到查询是?packages[]=xxx&packages[]=yyy&packages[]=zzz。但这正是useQuerystring: true 所做的。很奇怪……
【解决方案2】:

我终于找到了解决办法。我使用 'qs' 用 {arrayFormat : 'brackets'} 对 'options' 进行字符串化,然后连接到以 '?' 结尾的 url如下:

var request = require('request');
var qs1 = require('qs');

var getLibs = function() {
    var options = qs1.stringify({ 
        packages: ['example1', 'example2', 'example3'], 
        os: 'linux', 
        pack_type: 'npm' 
        },{
        arrayFormat : 'brackets'
    });


    request({url:'http://localhost:3000/package?' + options}, 
    function (error , response, body) {
        if (! error && response.statusCode == 200) {
            console.log(body);
        } else if (error) {
            console.log(error);
        } else{
            console.log(response.statusCode);
        }
    });
}();

注意:我试图避免连接到 url,但所有响应都有代码 400

【讨论】:

    【解决方案3】:

    这个问题可以使用 Request 库本身来解决。 请求内部使用 qs.stringify。您可以传递 q 选项来请求它将用于解析数组参数。

    您不需要附加到 url,这会让读者质疑为什么会这样做。

    参考:https://github.com/request/request#requestoptions-callback

    const options = {
      method: 'GET',
      uri: 'http://localhost:3000/package',
      qs: {
        packages: ['example1', 'example2', 'example3'], 
        os: 'linux', 
        pack_type: 'npm' 
      },
      qsStringifyOptions: {
        arrayFormat: 'repeat' // You could use one of indices|brackets|repeat
      },
      json: true
    };
    

    【讨论】:

      猜你喜欢
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-21
      • 1970-01-01
      • 2019-07-19
      • 1970-01-01
      相关资源
      最近更新 更多