mirror of
https://github.com/nlohmann/json.git
synced 2026-10-29 20:15:20 +00:00
* 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>
157 lines
6.0 KiB
Markdown
157 lines
6.0 KiB
Markdown
# Parsing and Exceptions
|
|
|
|
When the input is not valid JSON, an exception of type [`parse_error`](../../home/exceptions.md#parse-errors) 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](../../home/exceptions.md#parse-errors). In case you process untrusted
|
|
input, always enclose your code with a `#!cpp try`/`#!cpp catch` block, like
|
|
|
|
```cpp
|
|
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()`](../../api/basic_json/parse.md) 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`).
|
|
|
|
```cpp
|
|
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()`](../../api/basic_json/accept.md) can be used which does not return a `json` value,
|
|
but a `#!cpp bool` indicating whether the input is valid JSON.
|
|
|
|
```cpp
|
|
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](sax_interface.md) and decide what should happen in case of a parse error.
|
|
|
|
This function has the following interface:
|
|
|
|
```cpp
|
|
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`](../../home/exceptions.md#jsonexceptionparse_error101) 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](sax_interface.md). 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`](../../api/macros/json_diagnostic_positions.md) 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()`](../../api/basic_json/start_pos.md) and [`end_pos()`](../../api/basic_json/end_pos.md):
|
|
|
|
??? 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`](../../api/basic_json/parse.md), 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](large_and_partial_input.md#several-values-in-one-stream).
|
|
|
|
## See also
|
|
|
|
- [`parse`](../../api/basic_json/parse.md) - deserialize from a compatible input
|
|
- [`accept`](../../api/basic_json/accept.md) - check if the input is valid JSON
|
|
- [`sax_parse`](../../api/basic_json/sax_parse.md) - generate SAX events
|
|
- [`parse_error`](../../api/basic_json/parse_error.md) - exception thrown on a parse error
|
|
- [`JSON_DIAGNOSTIC_POSITIONS`](../../api/macros/json_diagnostic_positions.md) - record start and end positions of parsed values
|
|
- [Working Without Exceptions](../no_exceptions.md) - error handling when exceptions are disabled
|
|
- [Exceptions](../../home/exceptions.md) - list of exceptions and error codes
|
|
- [Parsing Untrusted Input](untrusted_input.md) - limits and checks for input you do not control
|