JSON Serialization and Deserialization
JavaScript values are serialized to JSON text when sending JSON request bodies and deserialized from JSON text when reading JSON responses. In browser code, `JSON.stringify()` performs serialization and `JSON.parse()` performs deserialization.
JSON is a text format used to represent structured data. JavaScript objects and arrays are in-memory values, while a JSON request body is text sent over HTTP. Serialization converts a JavaScript value into a JSON string, commonly with `JSON.stringify()`.
Deserialization performs the reverse operation: it converts JSON text into JavaScript values. With `fetch()`, `response.json()` reads the response body and parses valid JSON for you, so you usually do not call `JSON.parse()` on the result of `response.json()`.
Not every JavaScript value has a direct JSON representation. Functions and `undefined` are omitted from objects and become `null` in arrays; `Date` values are serialized through their string representation, and `BigInt` values cause `JSON.stringify()` to throw unless handled separately.
HTTP headers describe how a body should be interpreted. For a JSON request, `Content-Type: application/json` tells the server that the request body contains JSON. Serialization and deserialization are separate from HTTP itself: HTTP transports the bytes, while JSON defines the data representation.
Key points
- Use `JSON.stringify(value)` to serialize a JavaScript value into JSON text.
- Use `response.json()` to parse a JSON HTTP response when using `fetch()`.
- Set `Content-Type: application/json` when sending a JSON request body.
- JSON cannot represent every JavaScript value directly.
- Do not call `JSON.parse()` on a value already returned by `response.json()`.
- Serialization is conversion of data representation, not encryption or validation.
Interview questions
What is JSON serialization, and why is it needed with `fetch()`?
Serialization converts a JavaScript value into JSON text. HTTP request bodies are transmitted as data, and when an API expects JSON, the JavaScript object is commonly converted with `JSON.stringify()`. The resulting string can be supplied as the request body. The request should normally identify the representation with `Content-Type: application/json`.
How do you parse a JSON response from `fetch()`?
Call `response.json()` on the `Response` object. It reads the response body and parses it as JSON, returning a promise for the resulting JavaScript value. Because parsing is already performed by `response.json()`, you should not pass its result to `JSON.parse()`. You should also handle the possibility that the response body is not valid JSON when the API contract does not guarantee it.
What happens to `undefined` and functions during JSON serialization?
JSON has no representation for JavaScript functions or `undefined`. When these values occur as object properties, those properties are generally omitted by `JSON.stringify()`. When they occur as array elements, they are represented as `null`. This difference matters when serializing application state or request payloads because information can silently disappear.
Why is `Content-Type: application/json` important when sending JSON?
The header tells the server how to interpret the request body. A body produced by `JSON.stringify()` is JSON text, so `application/json` communicates that representation. Without the expected content type, some servers or middleware may not apply their JSON parser. The exact behavior depends on the server implementation.
What is the difference between serialization and validation?
Serialization changes a value from one representation into another, such as converting a JavaScript object into JSON text. Validation checks whether data satisfies an expected structure or set of constraints. `JSON.stringify()` can successfully serialize data that is still invalid for an API schema. Therefore, serialization should not be treated as a substitute for schema validation.