qs 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/lib/parse.js +13 -7
- package/lib/stringify.js +7 -3
- package/lib/utils.js +9 -7
- package/package.json +1 -1
- package/test/parse.js +13 -1
- package/test/stringify.js +6 -0
package/README.md
CHANGED
|
@@ -19,6 +19,10 @@ var str = Qs.stringify(obj); // 'a=c'
|
|
|
19
19
|
|
|
20
20
|
### Parsing Objects
|
|
21
21
|
|
|
22
|
+
```javascript
|
|
23
|
+
Qs.parse(string, [depth], [delimiter]);
|
|
24
|
+
```
|
|
25
|
+
|
|
22
26
|
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
|
|
23
27
|
For example, the string `'foo[bar]=baz'` converts to:
|
|
24
28
|
|
|
@@ -79,6 +83,13 @@ Qs.parse('a[b][c][d][e][f][g][h][i]=j', 1);
|
|
|
79
83
|
|
|
80
84
|
The depth limit mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number.
|
|
81
85
|
|
|
86
|
+
An optional delimiter can also be passed:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
Qs.parse('a=b;c=d', ';');
|
|
90
|
+
// { a: 'b', c: 'd' }
|
|
91
|
+
```
|
|
92
|
+
|
|
82
93
|
### Parsing Arrays
|
|
83
94
|
|
|
84
95
|
**qs** can also parse arrays using a similar `[]` notation:
|
|
@@ -137,6 +148,10 @@ Qs.parse('a[][b]=c');
|
|
|
137
148
|
|
|
138
149
|
### Stringifying
|
|
139
150
|
|
|
151
|
+
```javascript
|
|
152
|
+
Qs.stringify(object, [delimiter]);
|
|
153
|
+
```
|
|
154
|
+
|
|
140
155
|
When stringifying, **qs** always URI encodes output. Objects are stringified as you would expect:
|
|
141
156
|
|
|
142
157
|
```javascript
|
|
@@ -168,3 +183,9 @@ Properties that are set to `undefined` will be omitted entirely:
|
|
|
168
183
|
Qs.stringify({ a: null, b: undefined });
|
|
169
184
|
// 'a='
|
|
170
185
|
```
|
|
186
|
+
|
|
187
|
+
The delimiter may be overridden with stringify as well:
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
Qs.stringify({ a: 'b', c: 'd' }, ';');
|
|
191
|
+
// 'a=b;c=d'
|
package/lib/parse.js
CHANGED
|
@@ -6,16 +6,19 @@ var Utils = require('./utils');
|
|
|
6
6
|
// Declare internals
|
|
7
7
|
|
|
8
8
|
var internals = {
|
|
9
|
+
delimiter: '&',
|
|
9
10
|
depth: 5,
|
|
10
11
|
arrayLimit: 20,
|
|
11
12
|
parametersLimit: 1000
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
internals.parseValues = function (str) {
|
|
16
|
+
internals.parseValues = function (str, delimiter) {
|
|
17
|
+
|
|
18
|
+
delimiter = typeof delimiter === 'undefined' ? internals.delimiter : delimiter;
|
|
16
19
|
|
|
17
20
|
var obj = {};
|
|
18
|
-
var parts = str.split(
|
|
21
|
+
var parts = str.split(delimiter, internals.parametersLimit);
|
|
19
22
|
|
|
20
23
|
for (var i = 0, il = parts.length; i < il; ++i) {
|
|
21
24
|
var part = parts[i];
|
|
@@ -79,8 +82,6 @@ internals.parseKeys = function (key, val, depth) {
|
|
|
79
82
|
return;
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
depth = typeof depth === 'undefined' ? internals.depth : depth;
|
|
83
|
-
|
|
84
85
|
// The regex chunks
|
|
85
86
|
|
|
86
87
|
var parent = /^([^\[\]]*)/;
|
|
@@ -124,7 +125,7 @@ internals.parseKeys = function (key, val, depth) {
|
|
|
124
125
|
};
|
|
125
126
|
|
|
126
127
|
|
|
127
|
-
module.exports = function (str, depth) {
|
|
128
|
+
module.exports = function (str, depth, delimiter) {
|
|
128
129
|
|
|
129
130
|
if (str === '' ||
|
|
130
131
|
str === null ||
|
|
@@ -133,11 +134,16 @@ module.exports = function (str, depth) {
|
|
|
133
134
|
return {};
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
if (typeof depth !== 'number') {
|
|
138
|
+
delimiter = depth;
|
|
139
|
+
depth = internals.depth;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
var tempObj = typeof str === 'string' ? internals.parseValues(str, delimiter) : Utils.clone(str);
|
|
137
143
|
var obj = {};
|
|
138
144
|
|
|
139
145
|
// Iterate over the keys and setup the new object
|
|
140
|
-
|
|
146
|
+
//
|
|
141
147
|
for (var key in tempObj) {
|
|
142
148
|
if (tempObj.hasOwnProperty(key)) {
|
|
143
149
|
var newObj = internals.parseKeys(key, tempObj[key], depth);
|
package/lib/stringify.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
// Declare internals
|
|
5
5
|
|
|
6
|
-
var internals = {
|
|
6
|
+
var internals = {
|
|
7
|
+
delimiter: '&'
|
|
8
|
+
};
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
internals.stringify = function (obj, prefix) {
|
|
@@ -37,7 +39,9 @@ internals.stringify = function (obj, prefix) {
|
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
module.exports = function (obj) {
|
|
42
|
+
module.exports = function (obj, delimiter) {
|
|
43
|
+
|
|
44
|
+
delimiter = typeof delimiter === 'undefined' ? internals.delimiter : delimiter;
|
|
41
45
|
|
|
42
46
|
var keys = [];
|
|
43
47
|
|
|
@@ -47,5 +51,5 @@ module.exports = function (obj) {
|
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
return keys.join(
|
|
54
|
+
return keys.join(delimiter);
|
|
51
55
|
};
|
package/lib/utils.js
CHANGED
|
@@ -10,8 +10,7 @@ exports.arrayToObject = function (source) {
|
|
|
10
10
|
|
|
11
11
|
var obj = {};
|
|
12
12
|
for (var i = 0, il = source.length; i < il; ++i) {
|
|
13
|
-
if (source[i] !== undefined
|
|
14
|
-
source[i] !== null) {
|
|
13
|
+
if (typeof source[i] !== 'undefined') {
|
|
15
14
|
|
|
16
15
|
obj[i] = source[i];
|
|
17
16
|
}
|
|
@@ -54,8 +53,13 @@ exports.merge = function (target, source) {
|
|
|
54
53
|
|
|
55
54
|
if (Array.isArray(source)) {
|
|
56
55
|
for (var i = 0, il = source.length; i < il; ++i) {
|
|
57
|
-
if (source[i] !== undefined) {
|
|
58
|
-
obj[i]
|
|
56
|
+
if (typeof source[i] !== 'undefined') {
|
|
57
|
+
if (typeof obj[i] === 'object') {
|
|
58
|
+
obj[i] = exports.merge(obj[i], source[i]);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
obj[i] = source[i];
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
|
|
@@ -114,9 +118,7 @@ exports.compact = function (obj) {
|
|
|
114
118
|
compacted[key] = [];
|
|
115
119
|
|
|
116
120
|
for (var i = 0, l = obj[key].length; i < l; i++) {
|
|
117
|
-
if (obj[key]
|
|
118
|
-
obj[key][i] !== null) {
|
|
119
|
-
|
|
121
|
+
if (typeof obj[key][i] !== 'undefined') {
|
|
120
122
|
compacted[key].push(obj[key][i]);
|
|
121
123
|
}
|
|
122
124
|
}
|
package/package.json
CHANGED
package/test/parse.js
CHANGED
|
@@ -138,6 +138,7 @@ describe('#parse', function () {
|
|
|
138
138
|
expect(Qs.parse('foo[bad]=baz&foo[]=bar')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } });
|
|
139
139
|
expect(Qs.parse('foo[]=bar&foo[bad]=baz')).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } });
|
|
140
140
|
expect(Qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
141
|
+
expect(Qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb')).to.deep.equal({foo: [ {a: 'a', b: 'b'}, {a: 'aa', b: 'bb'} ]});
|
|
141
142
|
done();
|
|
142
143
|
});
|
|
143
144
|
|
|
@@ -236,8 +237,19 @@ describe('#parse', function () {
|
|
|
236
237
|
it('should not throw when a native prototype has an enumerable property', { parallel: false }, function (done) {
|
|
237
238
|
|
|
238
239
|
Object.prototype.crash = '';
|
|
239
|
-
|
|
240
|
+
Array.prototype.crash = '';
|
|
241
|
+
expect(Qs.parse.bind(null, 'a=b')).to.not.throw();
|
|
242
|
+
expect(Qs.parse('a=b')).to.deep.equal({ a: 'b' });
|
|
243
|
+
expect(Qs.parse.bind(null, 'a[][b]=c')).to.not.throw();
|
|
244
|
+
expect(Qs.parse('a[][b]=c')).to.deep.equal({ a: [{ b: 'c' }] });
|
|
240
245
|
delete Object.prototype.crash;
|
|
246
|
+
delete Array.prototype.crash;
|
|
247
|
+
done();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('parses a string with an alternative delimiter', function (done) {
|
|
251
|
+
|
|
252
|
+
expect(Qs.parse('a=b;c=d', ';')).to.deep.equal({ a: 'b', c: 'd' });
|
|
241
253
|
done();
|
|
242
254
|
});
|
|
243
255
|
});
|
package/test/stringify.js
CHANGED
|
@@ -120,4 +120,10 @@ describe('#stringify', function () {
|
|
|
120
120
|
expect(Qs.stringify({ a: { b: new Buffer('test') } })).to.equal('a%5Bb%5D=test');
|
|
121
121
|
done();
|
|
122
122
|
});
|
|
123
|
+
|
|
124
|
+
it('stringifies an object using an alternative delimiter', function (done) {
|
|
125
|
+
|
|
126
|
+
expect(Qs.stringify({ a: 'b', c: 'd' }, ';')).to.equal('a=b;c=d');
|
|
127
|
+
done();
|
|
128
|
+
});
|
|
123
129
|
});
|