-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathstringifyQuery.ts
More file actions
81 lines (74 loc) · 2.37 KB
/
stringifyQuery.ts
File metadata and controls
81 lines (74 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* qs.stringify와 동일한 기능을 제공하는 헬퍼 함수
*
* @param obj 직렬화할 객체
* @param options 옵션 객체
* @param options.indices 배열에 인덱스를 포함할지 여부 (기본값: true)
* @param options.addQueryPrefix 쿼리 문자열 앞에 '?'를 붙일지 여부 (기본값: true)
* @returns 쿼리 스트링 (기본적으로 '?' 접두사 포함)
*
* @example
* ```typescript
* // 기본 사용 (? 접두사 포함)
* stringifyQuery({limit: 10, status: 'active'}) // "?limit=10&status=active"
*
* // ? 접두사 제외
* stringifyQuery({limit: 10}, {addQueryPrefix: false}) // "limit=10"
*
* // 배열 처리 (인덱스 포함)
* stringifyQuery({tags: ['a', 'b']}) // "?tags[0]=a&tags[1]=b"
*
* // 배열 처리 (인덱스 제외)
* stringifyQuery({tags: ['a', 'b']}, {indices: false}) // "?tags=a&tags=b"
* ```
*/
export default function stringifyQuery(
obj: object | undefined | null,
options: {
/** 배열에 인덱스를 포함할지 여부 (기본값: true) */
indices?: boolean;
/** 쿼리 문자열 앞에 '?'를 붙일지 여부 (기본값: true) */
addQueryPrefix?: boolean;
} = {},
): string {
if (!obj || typeof obj !== 'object') {
return '';
}
if (Object.keys(obj).length === 0) {
return '';
}
const processValue = (key: string, value: unknown): string[] => {
if (Array.isArray(value)) {
if (options.indices === false) {
return value.map(
item =>
`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`,
);
}
return value.map(
(item, index) =>
`${encodeURIComponent(key)}[${index}]=${encodeURIComponent(String(item))}`,
);
}
if (value === null || value === undefined) {
return [];
}
if (typeof value === 'object') {
const nested: string[] = [];
for (const [subKey, subValue] of Object.entries(value)) {
nested.push(...processValue(`${key}[${subKey}]`, subValue));
}
return nested;
}
return [`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`];
};
const pairs: string[] = [];
for (const [key, value] of Object.entries(obj)) {
pairs.push(...processValue(key, value));
}
const queryString = pairs.join('&');
if (queryString) {
return options.addQueryPrefix === false ? queryString : `?${queryString}`;
}
return '';
}