From 06b186629db0c1461249150004b07950dce169ae Mon Sep 17 00:00:00 2001 From: Christophe Prakash Date: Sun, 13 Nov 2022 19:46:47 -0500 Subject: [PATCH 1/2] fetchBaseQuery | Add jsonReplacer param --- packages/toolkit/src/query/fetchBaseQuery.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index 5207ec5bc3..d3dbfb21af 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -132,6 +132,11 @@ export type FetchBaseQueryArgs = { * Defaults to `application/json`; */ jsonContentType?: string + + /** + * Custom replacer function used when calling `JSON.stringify()`; + */ + jsonReplacer?: (this: any, key: string, value: any) => any } & RequestInit & Pick @@ -178,6 +183,8 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * * @param {string} jsonContentType Used when automatically setting the content-type header for a request with a jsonifiable body that does not have an explicit content-type header. Defaults to `application/json`. * + * @param {(this: any, key: string, value: any) => any} jsonReplacer Custom replacer function used when calling `JSON.stringify()`. + * * @param {number} timeout * A number in milliseconds that represents the maximum time a request can take before timing out. */ @@ -188,6 +195,7 @@ export function fetchBaseQuery({ paramsSerializer, isJsonContentType = defaultIsJsonContentType, jsonContentType = 'application/json', + jsonReplacer, timeout: defaultTimeout, validateStatus: globalValidateStatus, ...baseFetchOptions @@ -247,7 +255,7 @@ export function fetchBaseQuery({ } if (isJsonifiable(body) && isJsonContentType(config.headers)) { - config.body = JSON.stringify(body) + config.body = JSON.stringify(body, jsonReplacer) } if (params) { From 8c380c262044d5eef2f89a707956c7a066c77c1d Mon Sep 17 00:00:00 2001 From: Christophe Prakash Date: Thu, 1 Dec 2022 14:43:07 -0500 Subject: [PATCH 2/2] Add test --- .../src/query/tests/fetchBaseQuery.test.tsx | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index eab78bd59b..7443aa05c4 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -431,6 +431,47 @@ describe('fetchBaseQuery', () => { expect(request.headers['content-type']).toBe('application/vnd.api+json') }) + + it('supports a custom jsonReplacer', async () => { + const body = { + items: new Set(["A", "B", "C"]) + } + + let request: any + ;({ data: request } = await baseQuery( + { + url: '/echo', + body, + method: 'POST', + }, + commonBaseQueryApi, + {} + )) + + expect(request.headers['content-type']).toBe('application/json') + expect(request.body).toEqual({ items: {} }) // Set is not properly marshalled by default + + // Use jsonReplacer + const baseQueryWithReplacer = fetchBaseQuery({ + baseUrl, + fetchFn: fetchFn as any, + jsonReplacer: (key, value) => value instanceof Set ? [...value] : value + }) + + ;({ data: request } = await baseQueryWithReplacer( + { + url: '/echo', + body, + method: 'POST', + }, + commonBaseQueryApi, + {} + )) + + expect(request.headers['content-type']).toBe('application/json') + expect(request.body).toEqual({ items: ["A", "B", "C"] }) // Set is marshalled correctly by jsonReplacer + + }) }) describe('arg.params', () => {