Files
json/docs/mkdocs/docs/features/serialization.md
T
Niels Lohmann 172eba6e46 docs: cross-link concept pages and API pages in See also sections
Add See also links in both directions between the concept pages (features,
home, integration) and the API pages, write API links in code font, give every
entry a comment after a dash, and show the callback event figure on the parser
callbacks page.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 16:17:03 +01:00

5.8 KiB

Serialization

Serialization is the process of turning a JSON value back into JSON text. It is the counterpart to parsing. The central function is dump, which returns the JSON text as a string.

json j = {{"pi", 3.141}, {"happy", true}};

std::string s = j.dump();   // {"happy":true,"pi":3.141}

To write a value directly to a stream (for example, a file or #!cpp std::cout), the operator<< is provided:

std::cout << j << std::endl;

!!! note "String, not raw value"

`dump` always returns a **JSON text**. Serializing a JSON string therefore includes the surrounding quotes and
escapes special characters. To obtain the *contained* string value without quotes, use
[`get<std::string>()`](conversions.md) instead of `dump`. See the [converting values](conversions.md) page.

Pretty-printing

By default, dump produces the most compact representation without any superfluous whitespace. Passing a non-negative indent argument pretty-prints the output with the given number of spaces per level:

??? example "Example: pretty-print JSON values with dump()"

```cpp
--8<-- "examples/dump.cpp"
```

Output:

```json
--8<-- "examples/dump.output"
```

The indentation character can be changed with the second argument (e.g., a tab #!cpp '\t'). An indent of 0 inserts newlines but no leading spaces, and the default of #!cpp -1 selects the compact single-line form.

Non-ASCII characters

Strings are stored and serialized as UTF-8 (see types). By default, dump copies valid non-ASCII characters as-is. Setting the third argument ensure_ascii to #!cpp true escapes all non-ASCII characters with \uXXXX sequences, so that the output contains only ASCII characters:

json j = "苹果";
j.dump();               // "苹果"
j.dump(-1, ' ', true);  // "\u82f9\u679c"

Handling invalid UTF-8

If a string contains invalid UTF-8 sequences (for example, because it holds data in another encoding such as Latin-1), serialization fails by default. The fourth argument of dump selects an error_handler:

  • strict (default) — throw a type_error.316 exception.
  • replace — replace invalid bytes with the Unicode replacement character U+FFFD (�).
  • ignore — silently drop invalid bytes.
  • keep — copy invalid bytes to the output unchanged; the result is not valid UTF-8.

??? example "Example: serialize invalid UTF-8 with different error handlers"

```cpp
--8<-- "examples/error_handler_t.cpp"
```

Output:

```json
--8<-- "examples/error_handler_t.output"
```

!!! tip "Avoiding invalid UTF-8"

The best fix is to ensure that all strings are UTF-8 encoded before storing them. See the
[FAQ on non-ASCII characters](../home/faq.md#parse-errors-reading-non-ascii-characters) for how to convert wide or
Latin-1 strings.

Numbers, NaN, and binary values

  • Numbers are serialized with enough precision to round-trip; see number serialization.
  • NaN and infinity cannot be represented in JSON and are serialized as #!json null; see NaN handling. The binary formats can preserve them.
  • Binary values have no JSON representation and are serialized as a helper object for debugging only; see binary values.

Using std::format, std::print, and fmt

Since version 3.12.0, JSON values can be formatted directly with C++20's std::format whenever the standard library provides the <format> header (controlled by JSON_HAS_STD_FORMAT). This is enabled by the std::formatter<basic_json> specialization, which also makes JSON values work with std::format_to and with C++23's std::print/std::println:

std::print("{}", j);      // compact, like j.dump()
std::print("{:2}", j);    // pretty-printed with indent 2 (like j.dump(2))
std::println("{:#}", j);  // pretty-printed with the default indent

The format spec mirrors the dump parameters: #!cpp "{:#}" pretty-prints, a width such as #!cpp "{:2}" sets the indent, and a fill-and-align prefix such as #!cpp "{:.>#}" sets the indent character.

For the {fmt} library, the library ships a format_as helper. Note its behavior depends on the fmt version; see the FAQ entry for the details and a recipe for a full fmt::formatter specialization.

Serializing to other formats

Besides JSON text, a value can also be serialized to the more compact binary formats (BJData, BON8, BSON, CBOR, MessagePack, UBJSON).

See also