Skip to content

Commit

Permalink
Add stringifyJson option (#579)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <[email protected]>
  • Loading branch information
Reverier-Xu and sindresorhus authored May 31, 2024
1 parent 2af72bf commit 2eea67e
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 1 deletion.
25 changes: 25 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,31 @@ const json = await ky('https://example.com', {
}).json();
```

##### stringifyJson

Type: `Function`\
Default: `JSON.stringify()`

User-defined JSON-stringifying function.

Use-cases:
1. Stringify JSON with a custom `replacer` function.

```js
import ky from 'ky';
import {DateTime} from 'luxon';

const json = await ky('https://example.com', {
stringifyJson: data => JSON.stringify(data, (key, value) => {
if (key.endsWith('_at')) {
return DateTime.fromISO(value).toSeconds();
}

return value;
})
}).json();
```

##### fetch

Type: `Function`\
Expand Down
2 changes: 1 addition & 1 deletion source/core/Ky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export class Ky {
}

if (this._options.json !== undefined) {
this._options.body = JSON.stringify(this._options.json);
this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json);
this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
this.request = new globalThis.Request(this.request, {body: this._options.body});
}
Expand Down
1 change: 1 addition & 0 deletions source/core/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const stop = Symbol('stop');
export const kyOptionKeys: KyOptionsRegistry = {
json: true,
parseJson: true,
stringifyJson: true,
searchParams: true,
prefixUrl: true,
retry: true,
Expand Down
26 changes: 26 additions & 0 deletions source/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,32 @@ export type KyOptions = {
*/
parseJson?: (text: string) => unknown;

/**
User-defined JSON-stringifying function.
Use-cases:
1. Stringify JSON with a custom `replacer` function.
@default JSON.stringify()
@example
```
import ky from 'ky';
import {DateTime} from 'luxon';
const json = await ky('https://example.com', {
stringifyJson: data => JSON.stringify(data, (key, value) => {
if (key.endsWith('_at')) {
return DateTime.fromISO(value).toSeconds();
}
return value;
})
}).json();
```
*/
stringifyJson?: (data: unknown) => string;

/**
Search parameters to include in the request URL. Setting this will override all existing search parameters in the input URL.
Expand Down
20 changes: 20 additions & 0 deletions test/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -733,3 +733,23 @@ test('parseJson option with promise.json() shortcut', async t => {

await server.close();
});

test('stringifyJson option with request.json()', async t => {
const server = await createHttpTestServer({bodyParser: false});

const json = {hello: 'world'};
const extra = 'extraValue';

server.post('/', async (request, response) => {
const body = await parseRawBody(request);
t.is(body, JSON.stringify({data: json, extra}));
response.end();
});

await ky.post(server.url, {
stringifyJson: data => JSON.stringify({data, extra}),
json,
});

await server.close();
});

0 comments on commit 2eea67e

Please sign in to comment.