如何在查询字符串中传递数组?

582

是否有一种标准的方法可以通过查询字符串传递数组?

明确一点,我的查询字符串中有多个值,其中一个值将是数组值。我希望该查询字符串值被视为数组 - 我不希望该数组被分离开来,以至于它与其他查询字符串变量不可区分。

此外,根据这篇文章的回答,作者建议查询字符串不支持数组。这准确吗?

编辑:

基于@Alex的回答,没有标准的方法可以实现这一点,那么我的后续问题是什么是在PHPJavascript识别我正在读取的参数是一个数组的简单方法?

使用相同名称命名多个参数是否可接受,并且通过这种方式,我会知道它们属于一个数组吗?例如:

?myarray=value1&myarray=value2&myarray=value3...

或者这样做是不好的实践方法吗?


你使用的框架是什么?一些框架有助于将数组传递到查询字符串的方法。 - keyboardP
@keyboardP- 根据使用情况,PHP和Javascript。 - Yarin
3
为什么你要这样做,而不是直接这样做呢:myarray=value1,value2,value3? - Serodis
22
如果他需要通过逗号、问号、等号和不可打印字符,该怎么办? - Berry Tsakala
1
然而,?myarray=value1&myarray=value2&myarray=value3... 看起来太长了,记录系统中的每个请求太繁琐了。我更喜欢使用 ?myarray=value1,value2,value3... 的格式。 - 徐志鹏
12个回答

634

我发现了以下内容:

提交多值表单字段,即通过GET/POST变量提交数组,可以通过几种不同的方式完成,因为通常没有明确规定标准。

发送多值字段或数组的三种可能方式如下:

  • ?cars[]=Saab&cars[]=Audi (最佳方式- PHP将其读入数组中)
  • ?cars=Saab&cars=Audi (不好的方式- PHP只会注册最后一个值)
  • ?cars=Saab,Audi (尚未尝试)

表单示例

在表单上,多值字段可以采用多选的


3
我认为这个功能没有被像维基百科或W3C这样的通用来源记录,是因为它没有被Web框架广泛支持。PHP和Rails会自动将多个"key[]"查询参数转换为数组,而其他框架则不会。 - Carl G
4
Node.js 的 querystring 模块使用 ?cars=Saab&cars=Audi 的形式。 - SystemParadox
98
在Express(Node.js)中,?cars=Saab&cars=Audi?cars[]=Saab&cars[]=Audi都会被转换为数组。然而,?cars=Saab最终变成一个字符串,而?cars[]=Saab则是一个只有一个元素的数组。 - Trevor Dixon
6
你能用这种方法设置键吗?多维数组呢? - Qwerty
7
ASP.NET MVC 似乎无法读取格式 ?cars[]=Saab&cars[]=Audi。 可能是方括号不存在,或者方括号需要索引。 - Mr. Flibble
显示剩余13条评论

47

查询字符串携带文本数据,因此只能将数组展开、正确编码并以所选的表现形式传递:

p1=value1&pN=valueN...
data=[value1,...,valueN]
data={p1:value1,...,pN:valueN}

然后在服务器端代码中进行解码。


好的,感谢澄清。您能看到我修改后的问题吗?对于键,是否有必要做p1...pn,还是我可以只将多个键命名为“p”,这样我就知道它们都属于同一个数组了? - Yarin
1
你可以使用相同的名称;https://dev59.com/MnE95IYBdhLWcg3wrP-w 或者像Serodis评论中提到的那样,只需使用p=aa,bb,cc这种最明显的方式。 - Alex K.
非常有用,可以使用JSON.stringifyJSON.parse - charliebrownie
1
一个简单且常见的表示格式是JSON,在PHP中使用json_encode,然后在另一页上使用rawurlencodejson_decode - Edward

29
我认为没有标准方法。
每个网络环境都提供自己的方式。而且对于URL来说通常太短了 (某些浏览器上有256字节的限制)。当然,更长的数组/数据可以使用POST请求发送。 不过,有一些方法:
  1. 有一种PHP的方式,它在URL查询中使用方括号 ([,])。例如,像 ?array_name[]=item&array_name[]=item_2 这样的查询已被证明可以工作,尽管文档记录较少,PHP会自动将其转换为数组。来源:https://dev59.com/2G025IYBdhLWcg3wEhZb#9547490
  2. 对象数据交换格式(例如JSON - 官方网站PHP文档)也可以使用,如果它们具有将变量转换为字符串和从字符串转换回变量的方法(如JSON所做的那样)。
    此外,对于HTTP GET请求,需要一个URL编码器 (大多数编程语言都有) 来正确地编码字符串数据。
虽然“方括号方法”很简单且有效,但它仅限于PHP和数组。
如果需要在查询字符串中传递其他类型的变量(如类或在PHP以外的语言中传递变量),则建议使用JSON方法。 PHP中JSON方法的示例 (方法2):
$myarray = array(2, 46, 34, "dfg");
$serialized = json_encode($myarray)
$data = 'myarray=' . rawurlencode($serialized);
// Send to page via cURL, header() or other service.

接收页面的代码(PHP):

$myarray = json_decode($_GET["myarray"]); // Or $_POST["myarray"] if a post request.

2
Express.js还支持方括号表示法,在4.13.4上进行了测试。 - Steve Kehlet
如果你要使用json_encode,在传递为get参数时,最好将字符串进行base64编码和解码。 - billrichards

25

这对我有效:

在链接中,to属性具有值:

to="/filter/arr?fruits=apple&fruits=banana"

Route 可以处理这个:

path="/filter/:arr"

对于多个数组:

to="filter/arr?fruits=apple&fruits=banana&vegetables=potato&vegetables=onion"

路由保持不变。

截图

输入图像描述

更新: 为了实现这种字符串结构,query-string 是最好的包。

例如:

import { stringify, parse } from 'query-string';

const queryParams={
   fruits:['apple','banana'],
   vegetables:['potato','onion']
}
//arrayFormat can be bracket or comma 
stringify(queryParams, { arrayFormat: 'bracket' });

20

虽然URL的部分没有标准,但JavaScript有一个或多或少的标准。

Array.toString 方法返回由逗号分隔的项目字符串。

因此,如果将包含数组的对象传递给URLSearchParams并在其上调用toString(),它将反过来调用每个值的toString,导致类似于以下内容:

let data = {
  name: 'abc',
  values: ['abc', 123]
}

new URLSearchParams(data).toString();
// ?name=abc&values=abc,123 (with escaped comma characters)

这种格式在前端进行序列化和在任何服务器上进行解析都非常容易,而且无论上下文如何都很容易理解,因此它往往成为我用于在URL中发送数组数据的首选。


1
实际上它生成了转义后的结果:"str=abc&arr=abc%2C123" - Luckylooke
1
确实,我会更新代码以显示它。但重点仍然是一样的,即“标准”的js在数组中使用逗号。 - João Haas
9
URLSearchParams 只接受字符串参数,不接受数组!任何非字符串都会通过正常的 toString 行为自动转换为字符串。JavaScript 将数组转换为用逗号连接的字符串并不意味着这是 JavaScript 在 URL 中编码数组数据的标准方式。这仅仅是 JavaScript 在整个语言中将数组转换为字符串的方式。 - Scotty Jamison
1
(对我的评论进行了轻微更正 - 如果您将对象传递给URLSearchParams的构造函数,则唯一支持的属性值类型是字符串,任何非字符串属性值都会被强制转换。但构造函数支持其他不相关的数据类型)。 - Scotty Jamison
1
@ScottyJamison 有点“挖坟”,但没错,这肯定是正在发生的事情。我仍然认为让服务器遵循与前端相同的标准是一件好事,但我会更改描述以表示逗号分隔数组是数组字符串强制转换的标准。 - João Haas
显示剩余2条评论

14

请注意,query-string模块列出了它支持的不同类型的数组编码方式(https://www.npmjs.com/package/query-string):

例如{foo:['1','2','3']}可以被编码为:

'foo[]=1&foo[]=2&foo[]=3'
'foo[0]=1&foo[1]=2&foo[3]=3'
'foo=1,2,3'
'foo=1&foo=2&foo=3'
// Any custom separator can be used:
'foo=1|2|3'
// ... and more custom formats

这表明有许多解决方案被采用...


7

我认为对于那些想要在查询字符串中传递数组给servlet的人来说,这会很有帮助。我测试了下面的查询字符串,并使用req.getgetParameterValues()方法获得了数组值。以下是我通过浏览器传递的查询字符串。

  http://localhost:8080/ServletsTutorials/*.html? 
  myname=abc&initial=xyz&checkbox=a&checkbox=b

复选框是我的参数数组。


4
我使用React和Rails。我做了以下工作: js
  let params = {
    filter_array: ['A', 'B', 'C']
  }

  ...

  //transform params in URI

  Object.keys(params).map(key => {
    if (Array.isArray(params[key])) {
      return params[key].map((value) => `${key}[]=${value}`).join('&')
    }
  }
  //filter_array[]=A&filter_array[]=B&filter_array[]=C

2
在你的问题中提到了PHP和Javascript,但标签中没有。我看到这个问题是想传递一个数组到MVC.Net操作中。
我在这里找到了答案:期望的格式是你在问题中提出的那种,多个参数具有相同的名称。

2
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Andrew
@Andrew 这不是一个仅包含链接的答案。"期望的格式是您在问题中提出的格式,其中多个参数具有相同的名称。" - DCShannon

1
你可以使用http_build_query在PHP中从数组生成一个URL编码的查询字符串。虽然生成的查询字符串将会被展开,但你可以决定一个唯一的分隔符作为http_build_query方法的参数,这样在解码时,你可以检查使用了哪个分隔符。如果是你选择的唯一分隔符,那么它就是数组查询字符串,否则它将是普通的查询字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接