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

明确起见,我有一个具有多个值的查询字符串,其中一个值将是数组值。我希望查询字符串值被视为数组-我不希望数组被分解,以便它与其他查询字符串变量难以区分。

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

编辑:

基于@Alex的回答,没有标准的方法来做到这一点,所以我的后续是什么是一个简单的方法来识别我正在阅读的参数是一个数组在PHP和Javascript?

将多个参数命名为相同的名称是否可以接受,这样我就知道它们属于一个数组?例子:

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

或者这是一种不好的做法?


当前回答

你在问题中提到了PHP和Javascript,但没有在标签中提到。我提出这个问题的目的是将一个数组传递给MVC。网行动。

我在这里找到了问题的答案:预期的格式是您在问题中提出的格式,多个参数具有相同的名称。

其他回答

我觉得这对于正在寻找将查询字符串中的数组传递给servlet的人是有帮助的。我测试了下面的查询字符串,并能够使用req.getgetParameterValues()获得数组值;方法。下面是我通过浏览器传递的查询字符串。

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

复选框是这里的参数数组。

以下是我的结论:

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

发送多值字段或数组的三种可能的方法是:

?cars[]=Saab&cars[]=Audi (PHP将此读入数组的最佳方式) ?cars=Saab&cars=Audi(不好的方法- PHP只会记录最后一个值) ?汽车=萨博,奥迪(还没试过)

形式的例子

在表单中,多值字段可以采用选择框的形式设置为多个:

<form> 
    <select multiple="multiple" name="cars[]"> 
        <option>Volvo</option> 
        <option>Saab</option> 
        <option>Mercedes</option> 
    </select>
</form>

(注意:在这种情况下,将选择控件命名为some_name[]非常重要,这样得到的请求vars将被PHP注册为一个数组)

... 或多个相同名称的隐藏字段:

<input type="hidden" name="cars[]" value="Volvo">
<input type="hidden" name="cars[]" value="Saab">
<input type="hidden" name="cars[]" value="Mercedes">

注意:使用field[]表示多个值的文档很少。在维基百科中关于查询字符串的多值键的部分,或者在W3C文档中处理多选择输入的部分,我没有看到任何提到它。


更新

正如评论者所指出的,这是非常特定于框架的。一些例子:

查询字符串:

?list_a=1&list_a=2&list_a=3&list_b[]=1&list_b[]=2&list_b[]=3&list_c=1,2,3

Rails:

"list_a": "3", 
"list_b":[
    "1",
    "2",
    "3"
  ], 
"list_c": "1,2,3"

角:

 "list_a": [
    "1",
    "2",
    "3"
  ],
  "list_b[]": [
    "1",
    "2",
    "3"
  ],
  "list_c": "1,2,3"

(角)的讨论

参见node.js, Wordpress, ASP.net中的示例注释


维持秩序: 还有一件事要考虑的是,如果你需要维护你的项目的顺序(即数组作为一个有序的列表),你实际上只有一个选项,这是传递一个分隔的值列表,并显式地转换为一个数组自己。

查询字符串携带文本数据,所以没有选择,只能分解数组,正确编码,并以您选择的表示格式传递:

p1 = value1&pN =家…… data = (value1,…,家) data = {p1: value1,…,pN:家}

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

我使用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

你可以使用这些函数,但要确保不要在对象键上使用“-”。

// convert obj to url params function objToUrlParams(obj) { let toUrlParams = (obj, prefex = '') => { // create url params let urlParams = ""; // loop through obj for (let key in obj) { let val = obj[key]; if (val == null) continue; if (val == undefined) continue; // if(val == '') continue; // if val is an object then call toUrlParams if (val instanceof Array) { // convert val from Array to object let valToObj = {}; val.forEach((v, i) => { valToObj[i] = v; }); val = valToObj; } let newPrefex = prefex + key; if (val instanceof Object) { urlParams += toUrlParams(val, newPrefex + '-'); } else { urlParams += newPrefex + '=' + val; } urlParams += '&'; } // remove last & urlParams = urlParams.slice(0, -1); // return url params return urlParams; } // encodeURI return encodeURI(toUrlParams(obj)); } // convert url params to obj function urlParamsToObj(urlParams) { // decodeURI urlParams = decodeURI(urlParams); let toObj = (urlParams) => { let obj = {}; let urlParamsArr = urlParams.split('&'); let subUrlParramsObj = {}; // loop through urlParams for (let i = 0; i < urlParamsArr.length; i++) { let item = urlParamsArr[i]; // get key and value let key = item.split('=')[0]; let val = item.split('=')[1] ?? null; let keys = key.split('-'); if (val == "null") { val = null; } else if (val == "undefined") { val = undefined; } else if (val == "true") { val = true; } else if (val == "false") { val = false; } else if (val == "NaN") { val = NaN; } else if (val == "Infinity") { val = Infinity; } // if keys length is 1 then set obj[key] to val if (keys.length == 1) { // check if obj contains key if (obj.hasOwnProperty(key)) { // if obj[key] is an array then push val if (obj[key] instanceof Array) { obj[key].push(val); } else { // create array and push val obj[key] = [obj[key], val]; } } else { obj[key] = val; } } // if keys length is 2 then set obj[keys[0]][keys[1]] to val else if (keys.length > 1) { let key0 = keys[0]; // check if subUrlParramsObj contains keys[0] if (!subUrlParramsObj[key0]) { subUrlParramsObj[key0] = []; } // remove keys[0] from keys keys.shift(); // join keys with - key = keys.join('-'); let param = key + '=' + val; // add param to subUrlParramsObj[keys[0]] subUrlParramsObj[key0].push(param); } } // loop through subUrlParramsObj for (let key in subUrlParramsObj) { // join subUrlParramsObj[key] with & let val = subUrlParramsObj[key].join('&'); // set obj[key] to val obj[key] = toObj(val); } // return obj return obj; } return checkIfObjShouldBeArrayAndConvert(toObj(urlParams)); } // check if object should be converted to array, if its keys are numbers function checkIfObjShouldBeArrayAndConvert(obj) { // if obj is an array if (obj instanceof Array) { // loop through obj obj.forEach((item, i) => { // check if item is an object if (item instanceof Object) { // convert item to array obj[i] = checkIfObjShouldBeArrayAndConvert(item); } }); // return obj return obj; } // check if all keys are numbers let canConvertToArray = true; for (let key in obj) { // get value let val = obj[key]; // check if value is an object or Array if (val instanceof Object || val instanceof Array) { obj[key] = checkIfObjShouldBeArrayAndConvert(val); } if (isNaN(key)) { canConvertToArray = false; } } // order obj by keys let orderedObj = {}; Object.keys(obj).sort().forEach(function(key) { orderedObj[key] = obj[key]; }); // check if the first key is 0 if (Object.keys(orderedObj)[0] != 0) { canConvertToArray = false; } // check if the keys step is 1 let keys = Object.keys(orderedObj); // loop through keys for (let i = 0; i < keys.length - 1; i++) { // get key let key = keys[i]; // get next key let nextKey = keys[i + 1]; // get key step let keyStep = nextKey - key; // check if key step is 1 if (keyStep != 1) { canConvertToArray = false; break; } } // if all keys are numbers then convert obj to array if (canConvertToArray) { let arr = []; for (let key in orderedObj) { arr.push(orderedObj[key]); } return arr; } // return obj return obj; } // add params to url function addParamsToUrl(params, url = window.location.href) { // check if url has params if (url.indexOf('?') == -1) { url += '?'; } else { url += '&'; } return url + params ?? ''; } function addObjToUrl(obj, url = window.location.href) { return addParamsToUrl(objToUrlParams(obj), url); } // extract params from url function extractParamsFromUrl(url = window.location.href) { return urlParamsToObj(url.split('?')[1]); } // test let urlParams = objToUrlParams({ a: 1, b: "zad", c: { d: 2, e: "f" }, j: [1, 2, 3, 4] }); console.log(urlParams); // a=1&b=zad&c-d=2&c-e=f&j=1&j=2&j=3&j=4 let obj = urlParamsToObj(urlParams); console.log(obj); // { "a": "1", "b": "zad", "j": [ "1", "2", "3", "4" ], "c": { "d": "2", "e": "f" } }