diff --git a/src/types.ts b/src/types.ts index 8e641cd1c..7a4f42248 100644 --- a/src/types.ts +++ b/src/types.ts @@ -244,9 +244,13 @@ export interface CompletedBody { /** * The contents of the response, decoded, parsed as UTF-8 string, and * then parsed a JSON. The response is decoded and returned asynchronously - * as a Promise. + * as a Promise. This returns undefined if the body can't be decoded or + * isn't valid JSON. + * + * The result covers any JSON value by default, or you can pass a type + * argument to set the type you expect. */ - getJson(): Promise; + getJson(): Promise; /** * The contents of the response, decoded, and then parsed automatically as diff --git a/src/util/request-utils.ts b/src/util/request-utils.ts index 947b76dab..2eaa540a8 100644 --- a/src/util/request-utils.ts +++ b/src/util/request-utils.ts @@ -230,9 +230,9 @@ export const buildBodyReader = ( (await this.getDecodedBuffer())!.toString() ); }, - async getJson() { + async getJson() { return runAsyncOrUndefined(async () => - JSON.parse((await completedBody.getText())!) + JSON.parse((await completedBody.getText())!) as R ) }, async getUrlEncodedFormData() { diff --git a/test/request-utils.spec.ts b/test/request-utils.spec.ts index 25090306e..ac114772a 100644 --- a/test/request-utils.spec.ts +++ b/test/request-utils.spec.ts @@ -89,6 +89,44 @@ nodeOnly(() => { }); }); + describe(".json", () => { + it('parses JSON objects', async () => { + const body = buildBodyReader(Buffer.from('{"a":1}'), {}); + expect(await body.getJson()).to.deep.equal({ a: 1 }); + }); + + it('parses JSON arrays', async () => { + const body = buildBodyReader(Buffer.from('[1,2]'), {}); + expect(await body.getJson()).to.deep.equal([1, 2]); + }); + + it('parses JSON primitives', async () => { + const numberBody = buildBodyReader(Buffer.from('42'), {}); + expect(await numberBody.getJson()).to.equal(42); + + const nullBody = buildBodyReader(Buffer.from('null'), {}); + expect(await nullBody.getJson()).to.equal(null); + }); + + it('can return an explicitly typed result', async () => { + const body = buildBodyReader(Buffer.from('{"a":1}'), {}); + const json = await body.getJson<{ a: number }>(); + expect(json?.a).to.equal(1); + }); + + it('is undefined for invalid JSON', async () => { + const body = buildBodyReader(Buffer.from('{oops'), {}); + expect(await body.getJson()).to.equal(undefined); + }); + + it('is undefined for unknown encodings', async () => { + const body = buildBodyReader(Buffer.from('{"a":1}'), { + 'content-encoding': 'randomized' + }); + expect(await body.getJson()).to.equal(undefined); + }); + }); + }); describe("preprocessRequest", () => {