Files
json/docs/mkdocs/docs/api/macros/json_precise_stream_position.md
T
Niels Lohmann 330fbead59 Document clang-tidy exclusions, drop unneeded ones, and clean up doc examples (#5909)
* Document clang-tidy exclusions and drop unneeded ones

Re-enable every excluded check in a run of clang-tidy 22 over all tests
and remove the seven that never fire (cert-err58-cpp,
clang-analyzer-webkit.NoUncountedMemberChecker,
cppcoreguidelines-virtual-class-destructor, google-readability-function-size,
hicpp-function-size, hicpp-no-assembler, readability-function-size).

Document the reason for every remaining exclusion at the top of the file.

Exclude in advance the checks that only exist in clang-tidy 23 and are
noise here (bugprone-signed-bitwise, *-explicit-constructor,
readability-trailing-comma, modernize-use-string-view), plus
modernize-use-integer-sign-comparison, which needs C++20 std::cmp_less
and flags deliberate casts.

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

* Fix clang-tidy findings in documentation examples and replace redundant aliases

Apply clang-tidy fixes to the documentation examples:
- performance-avoid-endl: std::endl -> '\n'
- readability-qualified-auto: auto -> auto* / const auto*
- performance-for-range-copy: copy -> const reference
- google-readability-casting: C-style cast -> static_cast

Replace redundant aliases (readability-redundant-qualified-alias) such as
"using json = nlohmann::json;" with "using nlohmann::json;" in the
documentation, README, examples, tests, and benchmarks. Aliases at class
scope and aliases of other types (with_base_class_t etc.) are kept.

No changes to the library or its public API. All changed examples were
compiled and run; their output matches the stored .output files (except
max_size and meta, which depend on the platform and compiler).

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

* Format doc examples with the pinned astyle

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-25 12:07:51 +01:00

4.7 KiB

JSON_PRECISE_STREAM_POSITION

#define JSON_PRECISE_STREAM_POSITION /* value */

When defined to 1, operator>> and sax_parse with strict = false leave a #!cpp std::istream positioned right after the parsed value for every value type. By default, the character that terminates a number is consumed as well.

The macro only affects reading from a #!cpp std::istream when the rest of the stream is not required to be consumed. parse, accept, and all other inputs (strings, iterators, containers, #!cpp FILE*) are never affected.

Default definition

The default value is 0 (disabled — existing behavior is preserved).

#define JSON_PRECISE_STREAM_POSITION 0

Notes

!!! note "Background"

A number is the only JSON value whose end can be detected solely by reading the character that follows it. By
default, that character is consumed and not put back, so the stream is left one byte too far after a number, and
only after a number:

```cpp
std::istringstream input("1true");
json j;
input >> j;  // j == 1, but the stream now starts at "rue"
```

With this macro, the character is only looked at and left in the stream, so the stream starts at `true`. This
does not require the stream buffer to support putting a character back.

This was not changed unconditionally, because code can depend on the consumed character, even unknowingly (see
[#5340](https://github.com/nlohmann/json/issues/5340)). Both of the following work by default only because the
character after each number is swallowed, and behave differently with this macro:

```cpp
std::istringstream input("1,2,3");
json j1, j2, j3;
input >> j1 >> j2 >> j3;  // default: 1, 2, 3
                          // with the macro: throws parse_error.101 at the ','
```

```cpp
std::istringstream input("42\nfoo");
json j;
std::string line;
input >> j;
std::getline(input, line);  // default: "foo"
                            // with the macro: "" (like after reading an int with >>)
```

In both cases, the behavior with the macro is what you already get today when the value is not a number: `"a","b"`
fails at the `,`, and `std::getline` after `{}` returns an empty string. This macro offers an opt-in path to
the consistent behavior ahead of version 4.0.0, where it is planned to become the default.

!!! warning "Opt-in only"

This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
effect.

!!! note "ABI compatibility"

The value of this macro is encoded in the [namespace](../../features/namespace.md) (tag `_psp`), resulting in
distinct symbol names. Translation units compiled with and without it can therefore be linked into the same program
without One Definition Rule (ODR) violations, but they cannot exchange instances of library types.

!!! note "Bulk scanning"

The parser scans the characters in the stream buffer in bulk (see
[`JSON_DISABLE_STREAM_BULK_SCAN`](json_disable_stream_bulk_scan.md)), but it never reads ahead. The stream is left
at the same position with and without bulk scanning, in both modes of this macro.

!!! tip "Workaround without the macro"

Separate the values in the stream with whitespace. The character consumed after a number is then the separator,
and whitespace before the next value is skipped anyway.

Examples

??? example "Example: default behavior (macro not defined)"

Without the macro, the character after a number is consumed:

```cpp
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>

using nlohmann::json;

int main()
{
    std::istringstream input("1true");
    json j1, j2;
    input >> j1;  // j1 == 1
    input >> j2;  // throws parse_error.101: the stream now starts at "rue"
}
```

??? example "Example: opt-in precise stream position (macro defined to 1)"

With the macro, the stream is positioned right after the number:

```cpp
#define JSON_PRECISE_STREAM_POSITION 1
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>

using nlohmann::json;

int main()
{
    std::istringstream input("1true");
    json j1, j2;
    input >> j1;  // j1 == 1
    input >> j2;  // j2 == true
}
```

See also

Version history

  • Added in version 3.13.0.
  • Planned to become the default (with the macro removed) in version 4.0.0.