Correct documentation errors found while hunting for bugs
- patch/patch_inplace: list the JSON pointer errors parse_error.106-109 and out_of_range.402/404, and quote the actual parse_error.105 message. - unflatten: list parse_error.106/107/108 and out_of_range.404. - to_bson: list out_of_range.415 (binary subtype above 255) and note that 412 and 415 are new in 3.13.0. - to_string: state that string_t must be convertible to std::string, also in the StringType requirements table. - JSON Lines: a `while (input >> j)` loop also throws after the last value for concatenated JSON values; show a loop that works for both. - BON8: a string gets 0xFF only if nothing follows it in the message; a string at the end of an array or object is ended by 0xFE. - custom_string_type.hpp: add operator+=(char), which the "Always required" list asks for (json_pointer::to_string, flatten, unflatten, and diff did not compile), and an ADL int_to_string for diff and items. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
9 files changed
+82
-14
No files matched your search
@@ -26,10 +26,24 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of
|
- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of
|
||||||
an array of objects.
|
an array of objects.
|
||||||
- Throws [`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105) if the JSON patch is malformed (e.g.,
|
- Throws [`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105) if the JSON patch is malformed (e.g.,
|
||||||
mandatory attributes are missing); example: `"operation add must have member path"`.
|
mandatory attributes are missing); example: `"operation 'add' must have member 'path'"`.
|
||||||
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index is out of range.
|
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index is out of range.
|
||||||
|
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in a "path" or
|
||||||
|
"from" member begins with '0'; example: `"array index '01' must not begin with '0'"`.
|
||||||
|
- Throws [`parse_error.107`](../../home/exceptions.md#jsonexceptionparse_error107) if a "path" or "from" member is not
|
||||||
|
empty and does not begin with a slash (`/`); example: `"JSON pointer must be empty or begin with '/' - was: 'a'"`.
|
||||||
|
- Throws [`parse_error.108`](../../home/exceptions.md#jsonexceptionparse_error108) if a tilde (`~`) in a "path" or
|
||||||
|
"from" member is not followed by `0` or `1`; example: `"escape character '~' must be followed with '0' or '1'"`.
|
||||||
|
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a "path" or
|
||||||
|
"from" member is not a number; example: `"array index 'foo' is not a number"`.
|
||||||
|
- Throws [`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402) if the array index `-` is used
|
||||||
|
where an existing element is required (the "path" of "replace", the "from" of "move" and "copy"); example:
|
||||||
|
`"array index '-' (3) is out of range"`.
|
||||||
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a JSON pointer inside the patch
|
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a JSON pointer inside the patch
|
||||||
could not be resolved successfully in the current JSON value; example: `"key baz not found"`.
|
could not be resolved successfully in the current JSON value; example: `"key baz not found"`.
|
||||||
|
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a reference token of a JSON
|
||||||
|
pointer inside the patch cannot be resolved, e.g., `-` in a "remove" operation or `1a` for an array; example:
|
||||||
|
`"unresolved reference token '-'"`.
|
||||||
- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent
|
- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent
|
||||||
("add", "remove", "move")
|
("add", "remove", "move")
|
||||||
- Throws [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) if an "add" operation's target
|
- Throws [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) if an "add" operation's target
|
||||||
|
|||||||
@@ -22,10 +22,24 @@ No guarantees, value may be corrupted by an unsuccessful patch operation.
|
|||||||
- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of
|
- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of
|
||||||
an array of objects.
|
an array of objects.
|
||||||
- Throws [`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105) if the JSON patch is malformed (e.g.,
|
- Throws [`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105) if the JSON patch is malformed (e.g.,
|
||||||
mandatory attributes are missing); example: `"operation add must have member path"`.
|
mandatory attributes are missing); example: `"operation 'add' must have member 'path'"`.
|
||||||
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index is out of range.
|
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index is out of range.
|
||||||
|
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in a "path" or
|
||||||
|
"from" member begins with '0'; example: `"array index '01' must not begin with '0'"`.
|
||||||
|
- Throws [`parse_error.107`](../../home/exceptions.md#jsonexceptionparse_error107) if a "path" or "from" member is not
|
||||||
|
empty and does not begin with a slash (`/`); example: `"JSON pointer must be empty or begin with '/' - was: 'a'"`.
|
||||||
|
- Throws [`parse_error.108`](../../home/exceptions.md#jsonexceptionparse_error108) if a tilde (`~`) in a "path" or
|
||||||
|
"from" member is not followed by `0` or `1`; example: `"escape character '~' must be followed with '0' or '1'"`.
|
||||||
|
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a "path" or
|
||||||
|
"from" member is not a number; example: `"array index 'foo' is not a number"`.
|
||||||
|
- Throws [`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402) if the array index `-` is used
|
||||||
|
where an existing element is required (the "path" of "replace", the "from" of "move" and "copy"); example:
|
||||||
|
`"array index '-' (3) is out of range"`.
|
||||||
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a JSON pointer inside the patch
|
- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a JSON pointer inside the patch
|
||||||
could not be resolved successfully in the current JSON value; example: `"key baz not found"`.
|
could not be resolved successfully in the current JSON value; example: `"key baz not found"`.
|
||||||
|
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a reference token of a JSON
|
||||||
|
pointer inside the patch cannot be resolved, e.g., `-` in a "remove" operation or `1a` for an array; example:
|
||||||
|
`"unresolved reference token '-'"`.
|
||||||
- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent
|
- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent
|
||||||
("add", "remove", "move")
|
("add", "remove", "move")
|
||||||
- Throws [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) if an "add" operation's target
|
- Throws [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) if an "add" operation's target
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
- Throws [`out_of_range.412`](../../home/exceptions.md#jsonexceptionout_of_range412) if the length of a document, array,
|
- Throws [`out_of_range.412`](../../home/exceptions.md#jsonexceptionout_of_range412) if the length of a document, array,
|
||||||
string, or binary value exceeds the range of the 32-bit BSON length field; example:
|
string, or binary value exceeds the range of the 32-bit BSON length field; example:
|
||||||
`"BSON length 2147483661 exceeds maximum of 2147483647"`
|
`"BSON length 2147483661 exceeds maximum of 2147483647"`
|
||||||
|
- Throws [`out_of_range.415`](../../home/exceptions.md#jsonexceptionout_of_range415) if the subtype of a binary value
|
||||||
|
exceeds 255, the maximum of the BSON binary subtype; example:
|
||||||
|
`"subtype 300 is too large for the BSON binary subtype (max 255)"`
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
@@ -92,4 +95,5 @@ pass before anything is written.
|
|||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.4.0.
|
- Added in version 3.4.0.
|
||||||
|
- Throws `out_of_range.412` and `out_of_range.415` since version 3.13.0.
|
||||||
- Linear in the size of `j`, and no longer limited by the call stack for deeply nested values, since version 3.13.0.
|
- Linear in the size of `j`, and no longer limited by the call stack for deeply nested values, since version 3.13.0.
|
||||||
@@ -10,7 +10,8 @@ This function implements a user-defined to_string for JSON objects.
|
|||||||
## Template parameters
|
## Template parameters
|
||||||
|
|
||||||
`BasicJsonType`
|
`BasicJsonType`
|
||||||
: a specialization of [`basic_json`](index.md)
|
: a specialization of [`basic_json`](index.md) whose [`string_t`](string_t.md) is convertible to `#!cpp std::string`;
|
||||||
|
for other string types, use [`dump`](dump.md), which returns a `string_t`
|
||||||
|
|
||||||
## Return value
|
## Return value
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,17 @@ The function can throw the following exceptions:
|
|||||||
- Throws [`type_error.315`](../../home/exceptions.md#jsonexceptiontype_error315) if object values are not primitive
|
- Throws [`type_error.315`](../../home/exceptions.md#jsonexceptiontype_error315) if object values are not primitive
|
||||||
- Throws [`type_error.313`](../../home/exceptions.md#jsonexceptiontype_error313) if a key (JSON pointer) leads to a
|
- Throws [`type_error.313`](../../home/exceptions.md#jsonexceptiontype_error313) if a key (JSON pointer) leads to a
|
||||||
conflicting nesting; example: `"invalid value to unflatten"`
|
conflicting nesting; example: `"invalid value to unflatten"`
|
||||||
|
- Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in a key begins
|
||||||
|
with '0'; example: `"array index '01' must not begin with '0'"`
|
||||||
|
- Throws [`parse_error.107`](../../home/exceptions.md#jsonexceptionparse_error107) if a key is not empty and does not
|
||||||
|
begin with a slash (`/`); example: `"JSON pointer must be empty or begin with '/' - was: 'a'"`
|
||||||
|
- Throws [`parse_error.108`](../../home/exceptions.md#jsonexceptionparse_error108) if a tilde (`~`) in a key is not
|
||||||
|
followed by `0` or `1`; example: `"escape character '~' must be followed with '0' or '1'"`
|
||||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a key is not a
|
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a key is not a
|
||||||
number; example: `"array index 'one' is not a number"`
|
number; example: `"array index 'one' is not a number"`
|
||||||
|
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a level becomes an array
|
||||||
|
(because one of its keys is `0`) and another key at that level cannot be an array index; example:
|
||||||
|
`"unresolved reference token 'x'"`
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -8,10 +9,10 @@
|
|||||||
// and nothing more of std::string's interface.
|
// and nothing more of std::string's interface.
|
||||||
//
|
//
|
||||||
// Covers the "Always required" members, the extras needed for the binary
|
// Covers the "Always required" members, the extras needed for the binary
|
||||||
// formats, and the extras needed for JSON Pointer / flatten / unflatten /
|
// formats, JSON Pointer / flatten / unflatten, and the int_to_string overload
|
||||||
// diff. Extending it further (e.g. for std::hash<basic_json> or to_bson) is
|
// needed for diff and items. Extending it further (e.g. for
|
||||||
// a matter of adding the extra members listed in the "Required for other
|
// std::hash<basic_json> or to_bson) is a matter of adding the extra members
|
||||||
// functionality" table.
|
// listed in the "Required for other functionality" table.
|
||||||
//
|
//
|
||||||
// See https://json.nlohmann.me/features/types/template_parameters/#stringtype
|
// See https://json.nlohmann.me/features/types/template_parameters/#stringtype
|
||||||
class custom_string_type
|
class custom_string_type
|
||||||
@@ -93,6 +94,11 @@ class custom_string_type
|
|||||||
data_.append(other.data_);
|
data_.append(other.data_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
custom_string_type& operator+=(char c)
|
||||||
|
{
|
||||||
|
data_.push_back(c);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
size_type find_first_of(char c, size_type pos = 0) const
|
size_type find_first_of(char c, size_type pos = 0) const
|
||||||
{
|
{
|
||||||
@@ -116,6 +122,12 @@ class custom_string_type
|
|||||||
return data_.end();
|
return data_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// found by ADL; converts array indices to keys in diff and items
|
||||||
|
friend void int_to_string(custom_string_type& target, std::size_t value)
|
||||||
|
{
|
||||||
|
target.data_ = std::to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
friend bool operator==(const custom_string_type& lhs, const custom_string_type& rhs)
|
friend bool operator==(const custom_string_type& lhs, const custom_string_type& rhs)
|
||||||
{
|
{
|
||||||
return lhs.data_ == rhs.data_;
|
return lhs.data_ == rhs.data_;
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ The library uses the following mapping from JSON values types to BON8 types acco
|
|||||||
|
|
||||||
An integer that takes 2 to 4 bytes starts with a UTF-8 lead byte (0xC2..0xF7) that is followed by a byte that cannot
|
An integer that takes 2 to 4 bytes starts with a UTF-8 lead byte (0xC2..0xF7) that is followed by a byte that cannot
|
||||||
continue a UTF-8 character: 0x00..0x7F for positive and 0xC0..0xFF for negative integers. A string is terminated by
|
continue a UTF-8 character: 0x00..0x7F for positive and 0xC0..0xFF for negative integers. A string is terminated by
|
||||||
0xFF only if it is empty, if another string follows it, or if it is the last value of the message; otherwise, the first
|
0xFF only if it is empty, if another string follows it, or if nothing follows it in the message; otherwise, the byte
|
||||||
byte of the next value ends it.
|
after it ends it: the first byte of the next value, or the 0xFE that ends an array or object. For example, `["e"]` is
|
||||||
|
serialized as 0x81 0x65 0xFF, but `[1,2,3,4,"e"]` as 0x85 0x91 0x92 0x93 0x94 0x65 0xFE.
|
||||||
|
|
||||||
!!! success "Complete mapping"
|
!!! success "Complete mapping"
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ Non-negative integers are read as number_unsigned, negative integers as number_i
|
|||||||
arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a
|
arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a
|
||||||
string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.
|
string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.
|
||||||
|
|
||||||
Strings must be valid UTF-8, and the last string of a message must be terminated by 0xFF.
|
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,20 @@ JSON Lines input with more than one value is treated as invalid JSON by the [`pa
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
with a JSON Lines input does not work, because the parser will try to parse one value after the last one.
|
with a JSON Lines input does not work, because the parser will try to parse one value after the last one and throw
|
||||||
|
a [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) exception. The same happens for a
|
||||||
|
stream of *concatenated* (non-newline-delimited) JSON values: `operator>>` reads them one at a time, but the loop
|
||||||
|
above throws after the last value. To read either format with `operator>>`, check for the end of the stream before
|
||||||
|
each read:
|
||||||
|
|
||||||
This is different from parsing a stream of *concatenated* (non-newline-delimited) JSON values, for which
|
```cpp
|
||||||
`operator>>` does work, provided that a value that is a number is followed by whitespace -- see its
|
json j;
|
||||||
[notes](../../api/operator_gtgt.md#notes) for details.
|
while (input >> std::ws && input.peek() != std::char_traits<char>::eof())
|
||||||
|
{
|
||||||
|
input >> j;
|
||||||
|
std::cout << j << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A value that is a number must be followed by whitespace -- see the [notes](../../api/operator_gtgt.md#notes) of
|
||||||
|
`operator>>` for details.
|
||||||
@@ -394,6 +394,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
|||||||
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
||||||
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
||||||
| `#!cpp operator<<(std::ostream&, const json_pointer&)` | streamability to `#!cpp std::ostream` |
|
| `#!cpp operator<<(std::ostream&, const json_pointer&)` | streamability to `#!cpp std::ostream` |
|
||||||
|
| [`to_string`](../../api/basic_json/to_string.md) | conversion of `StringType` to `#!cpp std::string` (the function returns a `#!cpp std::string`) |
|
||||||
| exception messages | `data()` and `size()`, or `begin()` and `end()` |
|
| exception messages | `data()` and `size()`, or `begin()` and `end()` |
|
||||||
|
|
||||||
### Compatible types
|
### Compatible types
|
||||||
|
|||||||
Reference in new issue
Block a user