Apply the review's wording fixes to the json_view documentation

- Copying is disabled because of its cost, not because of two documents
  borrowing the same buffer; the unique_ptr follows from move-only.
- Inputs: streams, FILE*, and wide characters (strings, arrays, pointers)
  are all supported and owned; point to parse_copy() for owned copies.
- The error replay only runs for failing input, builds no values, and is
  skipped with allow_exceptions = false.
- read() writes copied inputs into the previous owned copy.
- Views can dangle like std::string_view, and why there is no
  shared/weak pointer design.
- The 4 GiB limit (16-byte nodes, 16-byte scanner steps), streams being
  read to the end first, which macros apply, why materialize() has no
  source positions, and wording nits (accept() vs basic_json::accept(),
  is_binary, is_discarded, see-also lists, size table, "back into").

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-17 08:30:46 +02:00
1 parent bdb6966416
commit 6d3f0dae96
15 files changed
+84 -55

No files matched your search

@@ -12,6 +12,11 @@ Checks whether the input is valid JSON, accepting and rejecting exactly what
function never throws an exception for invalid input, and the returned `#!cpp bool` is the only result -- no document
is returned.
The result is the same as that of `BasicJsonType::accept()` by design; the difference is how the check is made. This
function runs the document's index builder (and discards the index), while `BasicJsonType::accept()` runs the SAX
parser with a handler that ignores every event. Use this one if you go on to parse the same input with
[`parse()`](parse.md) anyway, so that both use the same code; either is fine for a plain yes/no answer.
## Template parameters
`InputType`
@@ -16,8 +16,8 @@ basic_json_document(const basic_json_document&) = delete;
2. Move constructor. Takes over `other`'s index and, if owned, its text; `other` is left as an empty document. Views
taken from `other` before the move remain valid, because the index is heap-allocated independently of the
`basic_json_document` object.
3. `basic_json_document` is move-only. Copying is disabled because it would either duplicate a potentially large index
and text, or leave two documents claiming to borrow the same buffer.
3. `basic_json_document` is move-only. Copying is disabled because of its cost: a copy would duplicate the whole
index, the decoded-string buffer, and the owned text, while a move is enough in every use we know of.
## Parameters
@@ -30,7 +30,7 @@ No-throw guarantee: the default and move constructors never throw exceptions.
## Complexity
Constant, for the default and move constructors.
Constant.
## Examples
@@ -11,13 +11,14 @@ A parsed JSON text, held as a flat index of its values
([16 bytes per value](../../home/architecture.md#node-index-of-json-views)) instead of a tree of `BasicJsonType` values.
Strings and numbers stay in the source text; only strings that contain escapes are decoded, into one buffer owned by
the document. [`basic_json_view`](../basic_json_view/index.md) is a read-only handle to one value of a
`basic_json_document`; [`materialize()`](../basic_json_view/materialize.md) turns a subtree back into the
`basic_json_document`; [`materialize()`](../basic_json_view/materialize.md) turns a subtree into the
`BasicJsonType` value that [`BasicJsonType::parse()`](../basic_json/parse.md) would have produced for it.
A document may **borrow** the text it was parsed from (the caller's buffer must then outlive the document) or **own**
it (a copy, or an rvalue `#!cpp std::string` that was moved in); see [`owns_source`](owns_source.md). `basic_json_document`
is move-only: copying a document would either duplicate a potentially large index and text, or leave two documents
claiming to borrow the same buffer, so it is disabled.
is move-only: a copy would duplicate the whole index, the decoded-string buffer, and the owned text, and a move is
enough in every use we know of. The index, the decoded strings, and the owned text live in one heap block that the
document holds through a `#!cpp std::unique_ptr`; this is also why views survive a move of the document.
## Template parameters
@@ -4,7 +4,7 @@
bool owns_source() const noexcept;
```
Returns whether the document holds its own copy of the parsed text, as opposed to borrowing the caller's buffer.
Returns whether the document holds its own copy of the parsed text or is borrowing the caller's buffer.
## Return value
@@ -21,13 +21,15 @@ static basic_json_document parse(IteratorType first, IteratorType last,
Both overloads accept the same JSON text as [`BasicJsonType::parse()`](../basic_json/parse.md), with the same
`ignore_comments`/`ignore_trailing_commas` options, but build a [`basic_json_document`](index.md) (a flat index into
the input) instead of a tree of `BasicJsonType` values. The input must be byte-oriented (see the template parameters
below): not every input type of `BasicJsonType::parse()` is supported.
the input) instead of a tree of `BasicJsonType` values. They take the same inputs as `BasicJsonType::parse()`. Byte
inputs that stay alive can be borrowed; all others (streams, `#!cpp FILE*`, wide characters, non-contiguous
iterators) are read into a copy that the document owns -- see the Notes. Use [`parse_copy()`](parse_copy.md) to get an
owned copy of a borrowable input as well.
## Template parameters
`InputType`
: A byte-oriented input, one of:
: A compatible input, for instance:
- a `#!cpp std::string`, `#!cpp std::string_view`, or a C-style array of single-byte characters
- a pointer to a null-terminated string of single-byte characters (`#!cpp char`, `#!cpp signed char`,
@@ -35,12 +37,10 @@ below): not every input type of `BasicJsonType::parse()` is supported.
- a container for which `#!cpp obj.data()` and `#!cpp obj.size()` give contiguous single-byte access, e.g.
`#!cpp std::vector<char>` or `#!cpp std::vector<std::uint8_t>`
- an `#!cpp std::istream` object
- a wide string object (`#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string`), which is converted
to UTF-8
Other inputs are not supported: a `#!cpp FILE*`, and pointers to or arrays of wide characters (`#!cpp wchar_t`,
`#!cpp char16_t`, `#!cpp char32_t`) are rejected at compile time by a `#!cpp static_assert`. (Use
[`BasicJsonType::parse()`](../basic_json/parse.md) for these.)
- a `#!cpp FILE*` pointer
- wide characters (`#!cpp wchar_t`, `#!cpp char16_t`, `#!cpp char32_t`), which are converted to UTF-8: a wide
string object (`#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string`), an array (e.g. a wide
string literal), or a pointer to a null-terminated wide string
`IteratorType`
: an input iterator type, for instance a pair of pointers such as `ptr` and `ptr + len`, or a pair of
@@ -78,7 +78,9 @@ discarded; see [`is_discarded`](is_discarded.md).
Throws the same exception [`BasicJsonType::parse()`](../basic_json/parse.md) throws for the same input and options --
the same exception id, message, and position -- because on a failing input the library's own parser is run on the
same bytes to produce the diagnostic. Additionally throws
same bytes to produce the diagnostic. This replay runs only for a failing input, and costs about a lexing pass up to
the error (its SAX handler builds no values); with `allow_exceptions` set to `#!cpp false`, it is skipped and a
discarded document is returned instead. Additionally throws
[`out_of_range.416`](../../home/exceptions.md#jsonexceptionout_of_range416) if the input is 4294967280 bytes (4 GiB
minus 16 bytes) or larger, a size [`BasicJsonType::parse()`](../basic_json/parse.md) does not reject.
@@ -95,7 +97,7 @@ Linear in the length of the input.
| lvalue byte container (`std::string`, `std::vector<char>`, ...), `std::string_view`, C string, character array | **borrowed** -- `input` must outlive the document |
| non-const rvalue `#!cpp std::string` | **owned**, moved in without a copy |
| other rvalue byte container (including a `#!cpp const` rvalue `#!cpp std::string`) | **owned**, copied |
| stream, wide string, or anything else read through the general input adapter | **owned**, read into a buffer (a stream is read to its end) |
| stream, `#!cpp FILE*`, wide characters, or anything else read through the general input adapter | **owned**, read into a buffer (a stream is read to its end) |
For overload (2), a pair of pointers to single-byte integers (e.g. `#!cpp const char*`, `#!cpp std::uint8_t*`) is
borrowed. From C++20 on, so is any other contiguous iterator over single bytes, such as
@@ -47,7 +47,9 @@ Every view taken from `#!cpp *this` before the call -- including the previous [`
whether or not the new parse succeeds; take fresh views from [`root()`](root.md) afterward.
`input` is borrowed or owned by the same rules as [`parse()`](parse.md#notes); a document can borrow on one call and
own on the next, since ownership is decided freshly each time.
own on the next, since ownership is decided freshly each time. An input that is copied (see the table in
[`parse()`](parse.md#notes)) is written into the document's previous owned copy, reusing its memory; a moved-in
`#!cpp std::string` replaces it.
An integer argument that is not a `#!cpp bool` where the flags are expected, such as `#!cpp read(ptr, len)`, does not
compile; see [`parse`](parse.md#notes).
@@ -39,7 +39,8 @@ auto v = doc.root();
`root()` is a cheap handle into the document's index, not a copy of anything; call it as often as needed. The
returned view is valid under the same conditions as any other view of the document -- see
[Object inspection](../basic_json_view/index.md) -- in particular, it is invalidated by the next
[`read()`](read.md) or [`shrink_to_fit()`](shrink_to_fit.md) on this document.
[`read()`](read.md) or [`shrink_to_fit()`](shrink_to_fit.md) on this document. A view can dangle, like a
`#!cpp std::string_view`; see [Ownership and lifetime](../../features/json_view.md#ownership-and-lifetime).
## Examples
@@ -38,7 +38,8 @@ Constant.
## See also
- [is_structured](is_structured.md) - return whether the type is structured
- [size](size.md), [empty](empty.md) - the number of elements, and whether there are none
- [size](size.md) - the number of elements
- [empty](empty.md) - whether there are no elements
- [`BasicJsonType::is_array`](../basic_json/is_array.md) - the corresponding function of `basic_json`
## Version history
@@ -4,8 +4,9 @@
bool is_binary() const noexcept;
```
This function always returns `#!cpp false`: a JSON text has no binary values, so a view can never refer to one. The
function exists for interface parity with [`BasicJsonType::is_binary`](../basic_json/is_binary.md).
This function always returns `#!cpp false`: a document is only ever parsed from JSON text, never from CBOR or the other
binary formats, and a JSON text has no binary values, so a view can never refer to one. The function exists for
interface parity with [`BasicJsonType::is_binary`](../basic_json/is_binary.md).
## Return value
@@ -11,7 +11,7 @@ that is itself [discarded](../basic_json_document/is_discarded.md) -- in particu
## Return value
`#!cpp true` if the view is discarded, `#!cpp false` otherwise.
`#!cpp true` if the view or its document is discarded, `#!cpp false` otherwise.
## Exception safety
@@ -38,7 +38,8 @@ Constant.
## See also
- [is_structured](is_structured.md) - return whether the type is structured
- [size](size.md), [empty](empty.md) - the number of elements, and whether there are none
- [size](size.md) - the number of elements
- [empty](empty.md) - whether there are no elements
- [`BasicJsonType::is_object`](../basic_json/is_object.md) - the corresponding function of `basic_json`
## Version history
@@ -37,7 +37,8 @@ Constant.
## See also
- [source_offset](source_offset.md) - byte offset of this value in the document's source text
- [source_offset](source_offset.md) - byte offset of this value in the source text, which differs for strings: an
escaped string has none
- [`BasicJsonType::is_string`](../basic_json/is_string.md) - the corresponding function of `basic_json`
## Version history
@@ -14,8 +14,8 @@ if the view is [discarded](is_discarded.md).
## Exception safety
Strong guarantee: if an exception is thrown, there are no changes to the view or the document it refers to (nothing
about either is mutated by this function).
Strong guarantee: there are no changes to the view or the document it refers to (nothing about either is mutated by
this function).
## Exceptions
@@ -28,12 +28,13 @@ Linear in the size of the subtree.
## Notes
`materialize()` replays the subtree through the same SAX builder [`BasicJsonType::parse()`](../basic_json/parse.md)
uses internally, so the result matches it exactly -- including, for an object, that a repeated key keeps only its
uses, so the result matches it exactly -- including, for an object, that a repeated key keeps only its
last value. The replay is iterative, so it is not limited by the call stack the way a naive recursive conversion
would be; the JSON nesting depth is limited only by available memory, as for `BasicJsonType::parse()` itself.
Unlike parsing with [`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) enabled, the values
produced by `materialize()` do not carry source positions: there is no lexer run during the replay to record them.
produced by `materialize()` do not carry source positions. The index has the start offset of every value, but not the
end of arrays, objects, and escaped strings, which the positions also need.
Calling `materialize()` on the same view repeatedly builds a new, independent `BasicJsonType` value each time; it
never caches the result.
+9 -9
View File
@@ -10,15 +10,15 @@ Returns the number of elements, as [`BasicJsonType::size()`](../basic_json/size.
The return value depends on the type and is defined as follows:
| Value type | return value |
|----------------------|-----------------------------|
| null | `0` |
| discarded | `0` |
| boolean | `1` |
| string | `1` |
| number | `1` |
| object | number of key/value pairs |
| array | number of elements |
| Value type | return value |
|------------|---------------------------|
| null | `0` |
| discarded | `0` |
| boolean | `1` |
| string | `1` |
| number | `1` |
| object | number of key/value pairs |
| array | number of elements |
## Exception safety