Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for stringifyJson #579

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 25 additions & 0 deletions readme.md
Expand Up @@ -426,6 +426,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 the 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
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
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
Expand Up @@ -58,6 +58,32 @@ export type KyOptions = {
*/
parseJson?: (text: string) => unknown;

/**
User-defined JSON-stringifying function.

Use-cases:
1. Stringify JSON with the 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
23 changes: 23 additions & 0 deletions test/main.ts
Expand Up @@ -733,3 +733,26 @@ 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 result = {data: json, extra: 'extraValue'};

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

await ky.post(server.url, {
stringifyJson: data => JSON.stringify({
data,
extra: 'extraValue',
}),
sindresorhus marked this conversation as resolved.
Show resolved Hide resolved
Reverier-Xu marked this conversation as resolved.
Show resolved Hide resolved
json,
});

await server.close();
});