Skip to content

Return undefined instead of empty string from .json() on empty responses#828

Merged
sindresorhus merged 4 commits intomainfrom
json-undefined
Feb 23, 2026
Merged

Return undefined instead of empty string from .json() on empty responses#828
sindresorhus merged 4 commits intomainfrom
json-undefined

Conversation

@sindresorhus
Copy link
Copy Markdown
Owner

Fixes #732

// ergonomic "no content" handling.
if (response.status === 204) {
return '';
return undefined;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware it could be just return, but maybe having undefined there explicitly makes it slightly more readable.

Copy link
Copy Markdown
Collaborator

@sholladay sholladay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM but my opinion remains that we should return valid JSON if the method does not throw.

@sindresorhus
Copy link
Copy Markdown
Owner Author

but my opinion remains that we should return valid JSON if the method does not throw.

What exactly do you propose then?

  • Keep it ''. That's not valid JSON.
  • Go back to throwing again. Less user-friendly.

@sholladay
Copy link
Copy Markdown
Collaborator

My thinking was that an empty body is equivalent to an empty string, because HTTP is just text over the wire. And you can get an empty string back from the JSON parser.

JSON.parse('""') === '';
// => true

I take it back, though. I thought that JSON.parse('') was loose and also returned an empty string, but no. It throws, which I suppose is for the best. So we should treat them differently, too.

My other main reason for preferring an empty string over undefined was React's rendering behavior. I often parse JSON and then display it, e.g. for debugging. For a long time, rendering undefined would cause React to throw. But apparently they started allowing undefined in React 18. So that's moot now.

Let's do it. 👍

@sindresorhus sindresorhus merged commit 51e3552 into main Feb 23, 2026
8 of 9 checks passed
@sindresorhus sindresorhus deleted the json-undefined branch February 23, 2026 20:54
```
*/
json: <J = T>() => Promise<J>;
json: <J = T>() => Promise<J | undefined>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure you'll see this since it's merged, but widening to Promise<J | undefined> means that we have to guard against it at call sites which I wouldn't expect when explicitly passing in expected return type?

const response = http.get(`projects/${projectName}/build-number`).json<BuildNumberResponse>();

if (response !== undefined) { ... }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sindresorhus I've seen about 10 comments on this so far. Seems to be the most common issue people run into with 2.0.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KY is forcing empty string on 204

3 participants