Skip to content

Commit b952573

Browse files
committed
fix(query): remove undefined values
Close #3276
1 parent 982f334 commit b952573

File tree

2 files changed

+49
-30
lines changed

2 files changed

+49
-30
lines changed

src/util/query.js

+38-30
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ const commaRE = /%2C/g
99
// fixed encodeURIComponent which is more conformant to RFC3986:
1010
// - escapes [!'()*]
1111
// - preserve commas
12-
const encode = str => encodeURIComponent(str)
13-
.replace(encodeReserveRE, encodeReserveReplacer)
14-
.replace(commaRE, ',')
12+
const encode = str =>
13+
encodeURIComponent(str)
14+
.replace(encodeReserveRE, encodeReserveReplacer)
15+
.replace(commaRE, ',')
1516

1617
const decode = decodeURIComponent
1718

@@ -30,11 +31,15 @@ export function resolveQuery (
3031
}
3132
for (const key in extraQuery) {
3233
const value = extraQuery[key]
33-
parsedQuery[key] = Array.isArray(value) ? value.map(v => '' + v) : '' + value
34+
parsedQuery[key] = Array.isArray(value)
35+
? value.map(castQueryParamValue)
36+
: castQueryParamValue(value)
3437
}
3538
return parsedQuery
3639
}
3740

41+
const castQueryParamValue = value => (value == null ? value : '' + value)
42+
3843
function parseQuery (query: string): Dictionary<string> {
3944
const res = {}
4045

@@ -47,9 +52,7 @@ function parseQuery (query: string): Dictionary<string> {
4752
query.split('&').forEach(param => {
4853
const parts = param.replace(/\+/g, ' ').split('=')
4954
const key = decode(parts.shift())
50-
const val = parts.length > 0
51-
? decode(parts.join('='))
52-
: null
55+
const val = parts.length > 0 ? decode(parts.join('=')) : null
5356

5457
if (res[key] === undefined) {
5558
res[key] = val
@@ -64,33 +67,38 @@ function parseQuery (query: string): Dictionary<string> {
6467
}
6568

6669
export function stringifyQuery (obj: Dictionary<string>): string {
67-
const res = obj ? Object.keys(obj).map(key => {
68-
const val = obj[key]
69-
70-
if (val === undefined) {
71-
return ''
72-
}
70+
const res = obj
71+
? Object.keys(obj)
72+
.map(key => {
73+
const val = obj[key]
7374

74-
if (val === null) {
75-
return encode(key)
76-
}
75+
if (val === undefined) {
76+
return ''
77+
}
7778

78-
if (Array.isArray(val)) {
79-
const result = []
80-
val.forEach(val2 => {
81-
if (val2 === undefined) {
82-
return
79+
if (val === null) {
80+
return encode(key)
8381
}
84-
if (val2 === null) {
85-
result.push(encode(key))
86-
} else {
87-
result.push(encode(key) + '=' + encode(val2))
82+
83+
if (Array.isArray(val)) {
84+
const result = []
85+
val.forEach(val2 => {
86+
if (val2 === undefined) {
87+
return
88+
}
89+
if (val2 === null) {
90+
result.push(encode(key))
91+
} else {
92+
result.push(encode(key) + '=' + encode(val2))
93+
}
94+
})
95+
return result.join('&')
8896
}
89-
})
90-
return result.join('&')
91-
}
9297

93-
return encode(key) + '=' + encode(val)
94-
}).filter(x => x.length > 0).join('&') : null
98+
return encode(key) + '=' + encode(val)
99+
})
100+
.filter(x => x.length > 0)
101+
.join('&')
102+
: null
95103
return res ? `?${res}` : ''
96104
}

test/unit/specs/query.spec.js

+11
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,21 @@ describe('Query utils', () => {
2020
})
2121
})
2222

23+
it('should keep undefined and null query values', () => {
24+
const query = resolveQuery('', { a: undefined, b: null })
25+
expect(query).toEqual({ a: undefined, b: null })
26+
})
27+
28+
it('should keep null query values in arrays', () => {
29+
const query = resolveQuery('', { baz: [null, '2'] })
30+
expect(query).toEqual({ baz: [null, '2'] })
31+
})
32+
2333
it('should cast query values into string', () => {
2434
const query = resolveQuery('foo=bar&foo=k', { baz: 1 })
2535
expect(query.baz).toBe('1')
2636
})
37+
2738
it('should cast query array values into string', () => {
2839
const query = resolveQuery('foo=bar&foo=k', { baz: [1, '2'] })
2940
expect(query.baz).toEqual(['1', '2'])

0 commit comments

Comments
 (0)