JavaScript数组转URL编码

26
有没有JavaScript函数可以将数组转换为URL编码?我在JS方面完全是新手...谢谢!我的数组是一个键值对数组...
myData=new Array('id'=>'354313','fname'=>'Henry','lname'=>'Ford');

是相同的意思

myData['id']='354313';
myData['fname']='Henry';
myData['lname']='Ford';
myData.join('&'); //returns error, it doesn't work on such array...

有什么解决方案吗?


哦,抱歉... 我有一个这样的数组

var myData=new Array('id'=>'354313','fname'=>'Henry','lname'=>'Ford');

然后我需要将数组转换为:
id=354313&fname=Henry&lname=Ford

你是在说将数组中的每个字符串进行URL编码,还是将它们连接成一个URL查询字符串呢? - jerluc
Url编码仅适用于字符串。如果您希望将其应用于数组,则首先需要解释您的意思-您是否希望将数组连接成单个字符串?您是否希望对单个数组元素进行编码?您如何处理非字符串数组元素(例如对象、函数或其他数组)?最好编辑您的问题,包括至少一个您希望实现的示例(原始数组,生成的URL编码字符串)。 - Victor Nicollet
@theHack 你可以看一下我的回答 https://dev59.com/Ym445IYBdhLWcg3w499e#65610041 - Máxima Alekz
键值数组是对象,对于任何因措辞而感到困惑的人来说! - Rocky Kev
8个回答

34

试一下这个:

var myData = {'id': '354313', 'fname':'Henry', 'lname': 'Ford'};
var out = [];

for (var key in myData) {
    if (myData.hasOwnProperty(key)) {
        out.push(key + '=' + encodeURIComponent(myData[key]));
    }
}

out.join('&');

如果想了解为什么要使用hasOwnProperty,请查看这个回答"如何循环遍历JavaScript对象?".


2
最好这样做:out.push(key + '=' + encodeURIComponent(arr[key])); - Elia Weiss
这个数据不需要拥有自己的属性。 - ICW

19
如果您使用jQuery,可以使用$.param()。在这里查看。 使用示例。
var myData = {'id' : '354313', 'fname' : 'Henry', 'lname' : 'Ford'};
var url = "https://stackoverflow.com?" + $.param(myData);

输出为

https://stackoverflow.com?id=354313&fname=Henry&lname=Ford

同样适用于对象数组(例如通过 jQuery(form).serializeArray()):

var myData = [{'id' : '354313'}, {'fname' : 'Henry'},{'lname' : 'Ford'}];

14

你可以像这样做:

var myData = new Array('id=354313', 'fname=Henry', 'lname=Ford');
var url = myData.join('&');

7
我会选择使用 var url = '?' + myData.join('&'); - earthmeLon
@earthmeLon 这不是一个合适的解决方案,请查看 https://dev59.com/Ym445IYBdhLWcg3w499e#65610041 - Máxima Alekz

11

如果您使用对象而不是数组,则可以使用以下代码(ES6):

var myData = {
    id: 354313,
    fname: 'Henry',
    lname: 'Ford',
    url: 'https://es.wikipedia.org/wiki/Henry_Ford',
};

encodeDataToURL = (data) => {
    return Object
      .keys(data)
      .map(value => `${value}=${encodeURIComponent(data[value])}`)
      .join('&');
 }

console.log(encodeDataToURL(myData));

5
有点晚了,但我制作的这个解决方案可以处理递归和嵌套的数组/对象。
function is(className, object) {
    return Object.prototype.toString.call(object) === '[object '+ className +']';
}

const DataEncoder = function() {
    this.levels = [];
}

DataEncoder.prototype.__dataEncoding = function(data, actualKey = null) {
    let finalString = '';
    if (actualKey) {
        this.levels.push(actualKey);
    }

    const keys = Object.keys(data);
    const l = keys.length;
    for(let a = 0; a < l; a++) {
        const key = keys[a];
        let value = data[key];

        if (is('Object', value)) {
            finalString += this.__dataEncoding(value, key);
        } else if (is('Array', value)) {
            const arrValSize = value.length;
            for (let b = 0; b < arrValSize; b++) {
                let arrVal = value[b];
                if (actualKey) {
                    finalString += actualKey;
                    for(let c = 1; c < this.levels.length; c++) finalString += '[' + this.levels[c] + ']';
                    if (arrVal === undefined || arrVal === null) arrVal = '';
                    finalString += '[' + key + '][]=' + arrVal + '&';
                } else {
                    if (arrVal === undefined || arrVal === null) arrVal = '';
                    finalString += key + '[]=' + arrVal + '&';
                }
            }
        } else {
            if (actualKey) {
                finalString += this.levels[0];
                for(let c = 1; c < this.levels.length; c++) finalString += '[' + this.levels[c] + ']';
                if (value === undefined || value === null) value = '';
                finalString += '[' + key + ']=' + value + '&';
            } else {
                if (value === undefined || value === null) value = '';
                finalString += key + '=' + value + '&';
            }
        }
    }
    this.levels.pop();
    return finalString;
}

DataEncoder.prototype.encode = function(data) {
    if (!is('Object', data) || data === {}) return null;
    return this.__dataEncoding(data).slice(0, -1);
}

使用方法:

const testData = {
  name: "John",
  age: 13,
  skills: ['games', 'programming', 'reading', 'singing'],
  invests: {
    education: [120.3, 50.5],
    kids: 70,
    optical: {
      north: 20.5,
      south: 10.70,
      west: 6,
      east: [7]
    },
    deeper: {
      first: {
        landing: 5
      }
    }
  }
};
const encoder = new DataEncoder();
encoder.encode(testData);

结果:

name=John&age=13&skills[]=games&skills[]=programming&skills[]=reading&skills[]=singing&invests[education][]=120.3&invests[education][]=50.5&invests[kids]=70&invests[optical][north]=20.5&invests[optical][south]=10.7&invests[optical][west]=6&optical[optical][east][]=7&invests[deeper][first][landing]=5

我知道需要使用encodeURIComponent方法,但它可以很容易地添加


编辑,改进

function is(className, object) {
    return Object.prototype.toString.call(object) === '[object '+ className +']';
}

const DataEncoder = function() {
    this.levels = [];
    this.actualKey = null;

}

DataEncoder.prototype.__dataEncoding = function(data) {
    let uriPart = '';
    const levelsSize = this.levels.length;
    if (levelsSize) {
      uriPart = this.levels[0];
      for(let c = 1; c < levelsSize; c++) {
        uriPart += '[' + this.levels[c] + ']';
      }
    }
    let finalString = '';
    if (is('Object', data)) {
        const keys = Object.keys(data);
        const l = keys.length;
        for(let a = 0; a < l; a++) {
            const key = keys[a];
            let value = data[key];
            this.actualKey = key;
            this.levels.push(this.actualKey);
            finalString += this.__dataEncoding(value);
        }
    } else if (is('Array', data)) {
        if (!this.actualKey) throw new Error("Directly passed array does not work")
        const aSize = data.length;
        for (let b = 0; b < aSize; b++) {
            let aVal = data[b];
            this.levels.push(b);
            finalString += this.__dataEncoding(aVal);
        }
    } else {
        finalString += uriPart + '=' + encodeURIComponent(data) + '&';
    }
    this.levels.pop();
    return finalString;
}

DataEncoder.prototype.encode = function(data) {
    if (!is('Object', data) || !Object.keys(data).length) return null;
    return this.__dataEncoding(data).slice(0, -1);
}

现在它可以处理任何深度的嵌套数组/对象,这个编辑器的使用方式保持不变。

const testData = {
  name: "John",
  age: 13,
  skills: ['games', 'programming', 'reading', 'singing'],
  invests: {
    education: [120.3, 50.5],
    kids: 70,
    optical: {
      north: 20.5,
      south: 10.70,
      west: 6,
      east: [7]
    },
    deeper: {
      first: {
        landing: 5,
        arrayLike: [
          {
            despite: true,
            superb: 'yes',
            omg: {
              kiss: ['la'],
              maybe: {
                thiss: {
                  wont: {
                    work: 'false'
                  }
                }
              }
            },
            incredible: ['lalolanda', 'raidcall', 'phase', [5], [{waw: '@wesome'}]],
          }
        ]
      }
    }
  }
};
const encoder = new DataEncoder();
encoder.encode(testData);

结果:

name=John&age=13&skills[0]=games&skills[1]=programming&skills[2]=reading&skills[3]=singing&invests[education][0]=120.3&invests[education][1]=50.5&invests[kids]=70&invests[optical][north]=20.5&invests[optical][south]=10.7&invests[optical][west]=6&invests[optical][east][0]=7&invests[deeper][first][landing]=5&invests[deeper][first][arrayLike][0][despite]=true&invests[deeper][first][arrayLike][0][superb]=yes&invests[deeper][first][arrayLike][0][omg][kiss][0]=la&invests[deeper][first][arrayLike][0][omg][maybe][thiss][wont][work]=false&invests[deeper][first][arrayLike][0][incredible][0]=lalolanda&invests[deeper][first][arrayLike][0][incredible][1]=raidcall&invests[deeper][first][arrayLike][0][incredible][2]=phase&invests[deeper][first][arrayLike][0][incredible][3][0]=5&invests[deeper][first][arrayLike][0][incredible][4][0][waw]=%40wesome

1
你太棒了!稳定的解决方案! - flopperJ
需要改进以处理像 ["1","2","3"] 这样的简单数组。 - meYnot
@meYnot,你只需要发送类似{data: ["1","2","3"]}的内容,就可以正常工作了。 - Máxima Alekz

2
var myObject = {
  a: {
    one: 1,
    two: 2,
    three: 3
  },
  b: [ 1, 2, 3 ]
};
var recursiveEncoded = $.param( myObject );
var recursiveDecoded = decodeURIComponent( $.param( myObject ) );

alert( recursiveEncoded );
alert( recursiveDecoded );

递归编码和递归解码的值如下所示:
a%5Bone%5D=1&a%5Btwo%5D=2&a%5Bthree%5D=3&b%5B%5D=1&b%5B%5D=2&b%5B%5D=3 a[one]=1&a[two]=2&a[three]=3&b[]=1&b[]=2&b[]=3

https://api.jquery.com/jQuery.param/


0

参考jgrunds的回答,如果你想扩展数组功能

Array.prototype.toQueryString = function(){
    var out = new Array();

    for(key in this){
        out.push(key + '=' + encodeURIComponent(this[key]));
    }

    return out.join('&');
}

或者如果你想要一个独立的函数

function arrayToQueryString(array_in){
    var out = new Array();

    for(var key in array_in){
        out.push(key + '=' + encodeURIComponent(array_in[key]));
    }

    return out.join('&');
}

-1

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