Files
json/docs/mkdocs/docs/features/parsing/parse_exceptions.md
T
Niels Lohmann a47170346a docs: new design for the documentation site (#5934)
* docs: new design for the documentation site

Apply the brand to the Material for MkDocs site: Inter and JetBrains Mono
served by the site (upright and real italic), brand colours, blue header band
with the syntax pattern, wordmark in the header, new home page (hero, cards,
animated feature tour), 404 page, polish for tabs, search, footer, focus
rings, tables and code blocks, and theme features (code copy, previous/next
footer, TOC follow, search suggestions).

Draw the number railroad diagram, the parser callback events and the iterator
illustrations as inline SVGs that follow the light and dark scheme. The
generator scripts are in docs/mkdocs/scripts/figures; the feature slideshow
(json-light.svg, json-dark.svg, replacing json.gif on the home page) is built
by docs/mkdocs/scripts/slideshow. Decision nodes in five flowcharts become
hexagons, which need far less room.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* docs: add figures, table captions and a macro chooser

- Figures with numbered captions: SAX stepper, json_view layout and edit
  stepper, exception map, JSON pointer and patch walkers, QA pipeline,
  scaling and binary size charts, roadmap lanes, release timeline,
  integration decision tree and namespace builder
- Table captions (nj-table-caption) on 9 pages
- Compile times: modules and PCH charts, filesystem section, re-measured
  Figure 1, links between features/modules.md and compile_times.md
- Interactive macro chooser for features/arbitrary_types.md
- Link check: exclude URLs that answer the plugin with 400/401/419 or are
  dead (customers.md)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* docs: macro chooser generates adl_serializer for non-default-constructible types

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 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>

* docs: address review comments on the new design

- Home: add a "Latest release" button
- Sponsors: update the list and group it by tier
- Features: list all feature pages on the index page
- Releases: add highlights per release, link the 4.0 roadmap, add the first commit to the timeline
- Exceptions: prefix all example messages with the exception name
- API: no code font for format names in the See also links of the to_/from_ pages
- Merge Patch: show the document before, the patch, and the result
- Replace "--" with typographic dashes, mark external links with an icon, center Mermaid diagrams

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 07:41:42 +01:00

6.0 KiB

Parsing and Exceptions

When the input is not valid JSON, an exception of type parse_error is thrown. This exception contains the position in the input where the error occurred, together with a diagnostic message and the last read input token. The exceptions page contains a list of examples for parse error exceptions. In case you process untrusted input, always enclose your code with a #!cpp try/#!cpp catch block, like

json j;
try
{
    j = json::parse(my_input);
}
catch (json::parse_error& ex)
{
    std::cerr << "parse error at byte " << ex.byte << std::endl;
}

In case exceptions are undesired or not supported by the environment, there are different ways to proceed:

!!! tip

[Working without exceptions](../no_exceptions.md) also covers accessing values and converting to your own types.

Switch off exceptions

The parse() function accepts a #!cpp bool parameter allow_exceptions which controls whether an exception is thrown when a parse error occurs (#!cpp true, default) or whether a discarded value should be returned (#!cpp false).

json j = json::parse(my_input, nullptr, false);
if (j.is_discarded())
{
    std::cerr << "parse error" << std::endl;
}

Note there is no diagnostic information available in this scenario.

Use accept() function

Alternatively, function accept() can be used which does not return a json value, but a #!cpp bool indicating whether the input is valid JSON.

if (!json::accept(my_input))
{
    std::cerr << "parse error" << std::endl;
}

Again, there is no diagnostic information available.

User-defined SAX interface

Finally, you can implement the SAX interface and decide what should happen in case of a parse error.

This function has the following interface:

bool parse_error(std::size_t position,
                 const std::string& last_token,
                 const json::exception& ex);

The return value indicates whether the parsing should continue, so the function should usually return #!cpp false.

??? example "Example: report parse errors without exceptions"

The example derives from the library's DOM parser and overrides `parse_error` to print the error instead of
throwing. Note the DOM parser is an implementation detail (`nlohmann::detail`) and may change between releases;
see [Do not use the `detail` namespace](../../integration/migration_guide.md#do-not-use-the-detail-namespace).

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

Output:

```
--8<-- "examples/sax_no_exception.output"
```

Where did the error occur?

The message of a parse_error for JSON text contains the line and column of the error:

[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal

The exception object itself only stores the byte index of the last read character in the member byte (the first byte of the input has index 1). The same index is passed to parse_error in the SAX interface. If you need the line and column as numbers, for example to show them in an editor, compute them from the input:

??? example "Example: compute line and column of a parse error"

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

Output:

```
--8<-- "examples/parse_error_position.output"
```

Columns count bytes, so a line with multi-byte UTF-8 characters before the error may differ from the column your editor shows.

Where is the value that caused a later error?

A parse_error is raised while the text is read. Many mistakes show up later: the text is valid JSON, but a value has the wrong type when you convert it (type_error.302), or a key is missing (out_of_range.403). The exception then says what is wrong, but not where in the input the value was. Define JSON_DIAGNOSTIC_POSITIONS before including the library to add the byte range of the offending value to such messages (since version 3.12.0), and to query the range of any value with start_pos() and end_pos():

??? example "Example: locate a value with diagnostic positions"

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

Output:

```
--8<-- "examples/parse_error_position_diagnostic.output"
```

Positions are only available for values created by parse, they are not updated when a value is changed, and the macro makes every value 16 bytes larger on 64-bit platforms, so use it where the cost is acceptable, for example for configuration files. Note that start_pos() is a 0-based index into the input, whereas byte of a parse_error starts at 1.

For binary formats such as CBOR, there are no lines; byte is the position in the byte sequence. To find out how many bytes a successfully parsed value used, see Several values in one stream.

See also