mirror of
https://github.com/nlohmann/json.git
synced 2026-10-27 16:28:57 +00:00
Merge remote-tracking branch 'origin/develop' into docs-graphics
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
22 files changed
+613
-43
No files matched your search
@@ -61,11 +61,18 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
|
||||
## Complexity
|
||||
|
||||
Logarithmic in the size of the JSON object.
|
||||
1. Logarithmic in the size of the JSON object.
|
||||
2. Logarithmic in the size of the JSON object.
|
||||
3. At most one lookup per reference token of `ptr`, each logarithmic in the size of the container at that level:
|
||||
O(*n* log *m*) for *n* reference tokens and containers of size at most *m*.
|
||||
4. Deleted; a call with an integral argument does not compile.
|
||||
|
||||
## Notes
|
||||
|
||||
- This method always returns `#!cpp false` when executed on a JSON type that is not an object.
|
||||
- Overloads (1) and (2) always return `#!cpp false` when executed on a JSON type that is not an object. Overload (3)
|
||||
also works on arrays and on primitive values: the empty JSON pointer resolves in every JSON value (so
|
||||
`#!cpp json(1).contains(""_json_pointer)` returns `#!cpp true`), and `#!cpp json({1, 2}).contains("/1"_json_pointer)`
|
||||
returns `#!cpp true`.
|
||||
- This method can be executed on any JSON value type.
|
||||
- Calling this function with an integer argument (for example, `#!cpp contains(0)`) does not compile: such an argument
|
||||
would otherwise implicitly convert to a null `#!cpp const char*` and, from there, cause undefined behavior when
|
||||
|
||||
@@ -2,17 +2,27 @@
|
||||
|
||||
```cpp
|
||||
static basic_json diff(const basic_json& source,
|
||||
const basic_json& target);
|
||||
const basic_json& target,
|
||||
const string_t& path = "");
|
||||
```
|
||||
|
||||
Creates a [JSON Patch](http://jsonpatch.com) so that value `source` can be changed into the value `target` by calling
|
||||
[`patch`](patch.md) function.
|
||||
|
||||
For two JSON values `source` and `target`, the following code always yields `#!cpp true`:
|
||||
For two JSON values `source` and `target`, the following code yields `#!cpp true`:
|
||||
```cpp
|
||||
source.patch(diff(source, target)) == target;
|
||||
```
|
||||
|
||||
The equality holds up to [`operator==`](operator_eq.md), so it has the following exceptions:
|
||||
|
||||
- A value that is not equal to itself cannot round-trip. This applies to `NaN` (also nested in an array or object) and
|
||||
to [discarded](is_discarded.md) values: `diff` emits a `replace` operation for them. A `NaN` in the patch is
|
||||
serialized as `#!json null`, so a patch that was dumped and parsed again would set `#!json null`.
|
||||
- Numbers that compare equal produce no operation, even if their types or signs differ: `diff(1, 1.0)`,
|
||||
`diff(1u, 1)` (unsigned and signed integer) and `diff(0.0, -0.0)` all return `#!json []`. The patched value is then
|
||||
the `source` and keeps its number type.
|
||||
|
||||
## Parameters
|
||||
|
||||
`source` (in)
|
||||
@@ -21,6 +31,12 @@ source.patch(diff(source, target)) == target;
|
||||
`target` (in)
|
||||
: JSON value to compare against
|
||||
|
||||
`path` (in)
|
||||
: a prefix that is put verbatim in front of the `path` member of every operation (default: `""`, which addresses the
|
||||
root of the value). The prefix is neither escaped nor validated: `#!cpp diff(1, 2, "abc")` yields an operation with
|
||||
the `path` `abc`, which is not a valid JSON Pointer. Use it with a valid JSON Pointer such as `/root` and escape
|
||||
`~` and `/` in its reference tokens (see [JSON Pointer](../../features/json_pointer.md)).
|
||||
|
||||
## Return value
|
||||
|
||||
a JSON patch to convert the `source` to `target`
|
||||
@@ -31,11 +47,32 @@ Strong guarantee: `source` and `target` are never modified.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the lengths of `source` and `target`.
|
||||
Linear in the total number of values (including nested ones) in `source` and `target`, times the cost of a key-based
|
||||
object operation (looking up a key in an object): logarithmic for [`json`](../json.md), and linear for
|
||||
[`ordered_json`](../ordered_json.md) (see [`ordered_map` complexity](../ordered_map.md#complexity)). For
|
||||
`ordered_json`, diffing two objects with `n` and `m` members therefore takes O((n+m)²) when their keys do not line up
|
||||
(e.g., a key was added or the keys are in a different order). The size of the patch is proportional to the number of
|
||||
operations times the length of their paths, so a small change deep inside a value yields a long `path`.
|
||||
|
||||
## Notes
|
||||
|
||||
Currently, only `remove`, `add`, and `replace` operations are generated.
|
||||
- Currently, only `remove`, `add`, and `replace` operations are generated.
|
||||
- The patch is correct, but not guaranteed to be minimal. For instance, `diff([1,2,3], [0,1,2,3])` yields three
|
||||
`replace` operations and one `add` operation instead of a single insertion.
|
||||
- Differences between two arrays are reported index by index. Elements that were added at the end of the array are added
|
||||
with `add` operations on the path `/-` (appended in order), and elements that were removed are removed with `remove`
|
||||
operations from the highest index down to the lowest, so that the remaining indices stay valid.
|
||||
- For objects, the operations for the members of `source` come first (`replace`, `remove`, or the operations for nested
|
||||
values, in the iteration order of `source`), followed by `add` operations for the members that only `target` has.
|
||||
- For [`ordered_json`](../ordered_json.md), objects with the same keys in a different order are different. As a patch
|
||||
cannot reorder members, `diff` removes all keys of the `source` object and adds them again in the order of the
|
||||
`target`.
|
||||
- If `source` and `target` differ as a whole (e.g., different types), the patch consists of a single `replace`
|
||||
operation for the root of the value, i.e., with the `path` `""` (or the given `path` prefix).
|
||||
- The `value` members of the patch hold copies of values of `target`. A [binary](../../features/binary_values.md) value
|
||||
has no JSON representation: when a patch that contains one is serialized, it becomes an object such as
|
||||
`#!json {"bytes":[1,3],"subtype":null}`, so a parsed patch no longer holds a binary value (and would set that object
|
||||
instead).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -39,13 +39,33 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the lengths of `apply_patch`.
|
||||
Linear in the total number of values (including nested ones) in `apply_patch`, times the cost of a key-based object
|
||||
operation (looking up, adding, or erasing a member): logarithmic for [`json`](../json.md), and linear for
|
||||
[`ordered_json`](../ordered_json.md) (see [`ordered_map` complexity](../ordered_map.md#complexity)). For
|
||||
`ordered_json`, patching an object that has `n` members with a patch that has `m` members therefore takes O(n·m). The
|
||||
cost also includes one copy of `apply_patch` (see the notes below).
|
||||
|
||||
## Notes
|
||||
|
||||
`apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
|
||||
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
|
||||
`#!cpp *this`.
|
||||
- `apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
|
||||
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
|
||||
`#!cpp *this`. To make this possible, the function copies `apply_patch` before it modifies `#!cpp *this`, so the cost
|
||||
includes one copy of the patch.
|
||||
- A merge patch uses `#!json null` to remove a member, so it cannot set a member to `#!json null`: applying
|
||||
`#!json {"a":null}` to `#!json {"a":1}` gives `#!json {}`.
|
||||
- Arrays are not merged: an array in the patch replaces the target value as a whole, and a `#!json null` inside an
|
||||
array is kept as an element. `#!json null` members of the target that the patch does not mention are preserved.
|
||||
- A `#!json null` in the patch only removes a member; it does not prevent the creation of the enclosing objects.
|
||||
Applying `#!json {"a":{"b":null}}` to `#!json {}` gives `#!json {"a":{}}` (see example 15 in Appendix A of the RFC).
|
||||
- If `apply_patch` is not an object, it replaces the target as a whole. In particular, a `#!json null` patch turns the
|
||||
target into `#!json null`. If `apply_patch` is an object and the target is not, the target is first replaced by an
|
||||
empty object, so applying `#!json {}` to `#!json 1` gives `#!json {}`.
|
||||
- A merge patch cannot express every change; for example, it cannot reorder array elements or remove a specific array
|
||||
element. Use [JSON Patch](../../features/json_patch.md) ([RFC 6902](https://tools.ietf.org/html/rfc6902)) for that.
|
||||
[`merge_diff`](merge_diff.md) has a matching limitation, see its notes.
|
||||
- A [discarded](is_discarded.md) value is treated like any other non-object value: a discarded
|
||||
`apply_patch` turns the target into a discarded value, and an object patch replaces a discarded target by an object
|
||||
as described above.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -137,10 +137,13 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
|
||||
When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
|
||||
leaf), each missing level is created as an array or an object depending on whether the corresponding
|
||||
pointer token parses as a non-negative integer: a numeric token creates an array, a non-numeric token
|
||||
creates an object. For example, on an initially `#!json null` value, `/foo/0/0/0` creates nested arrays,
|
||||
while `/foo/one/one/one` creates nested objects. This is not specified by the JSON Pointer RFC; it is
|
||||
this library's own, intentional disambiguation rule. See also [JSON Pointer](../../features/json_pointer.md).
|
||||
pointer token is a valid array index: the token `0`, a sequence of digits that does not begin with `0`,
|
||||
or the token `-` creates an array, and every other token creates an object. For example, on an
|
||||
initially `#!json null` value, `/foo/0/0/0` creates nested arrays, while `/foo/one/one/one` creates
|
||||
nested objects. Tokens such as `01` or the empty token cannot be array indices (cf. RFC 6901, Sect. 4)
|
||||
and therefore create objects, just as they would if the level already existed as an object. This is not
|
||||
specified by the JSON Pointer RFC; it is this library's own, intentional disambiguation rule. See also
|
||||
[JSON Pointer](../../features/json_pointer.md).
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
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
|
||||
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 '-'"`.
|
||||
@@ -53,7 +53,10 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) if a "move" operation's "from"
|
||||
location is a proper prefix of its "path" location.
|
||||
- Throws [`other_error.501`](../../home/exceptions.md#jsonexceptionother_error501) if "test" operation was
|
||||
unsuccessful.
|
||||
unsuccessful. A "test" operation whose "path" does not exist is unsuccessful, too: the failed lookup is reported as a
|
||||
failed test, even if the operation has no "value" member (which would otherwise be
|
||||
[`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105)). Which of the two errors is reported for
|
||||
this combination depends on the order in which the operands of a comparison are evaluated, so do not rely on it.
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -65,6 +68,10 @@ the JSON value, the complexity can usually be neglected.
|
||||
The application of a patch is atomic: Either all operations succeed and the patched document is returned or an exception
|
||||
is thrown. In any case, the original value is not changed: the patch is applied to a copy of the value.
|
||||
|
||||
Duplicate member names inside an operation object are resolved by the parser before the patch is applied (the last one
|
||||
is kept, see [`object_t`](object_t.md#behavior)), so `#!json {"op": "add", "op": "remove", "path": "/a"}` is a
|
||||
`remove` operation.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: apply a JSON patch"
|
||||
@@ -110,6 +117,7 @@ is thrown. In any case, the original value is not changed: the patch is applied
|
||||
- Added in version 2.0.0.
|
||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||
target location has a non-object/non-array parent in version 3.13.0.
|
||||
This includes a `null` parent, which was previously silently converted to an object, in version 3.13.0.
|
||||
- Added [`out_of_range.413`](../../home/exceptions.md#jsonexceptionout_of_range413) and stopped silently ignoring a "remove" operation whose target
|
||||
location has a non-object/non-array parent in version 3.13.0.
|
||||
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
||||
|
||||
@@ -36,7 +36,7 @@ No guarantees, value may be corrupted by an unsuccessful patch operation.
|
||||
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
|
||||
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 '-'"`.
|
||||
@@ -49,7 +49,10 @@ No guarantees, value may be corrupted by an unsuccessful patch operation.
|
||||
- Throws [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) if a "move" operation's "from"
|
||||
location is a proper prefix of its "path" location.
|
||||
- Throws [`other_error.501`](../../home/exceptions.md#jsonexceptionother_error501) if "test" operation was
|
||||
unsuccessful.
|
||||
unsuccessful. A "test" operation whose "path" does not exist is unsuccessful, too: the failed lookup is reported as a
|
||||
failed test, even if the operation has no "value" member (which would otherwise be
|
||||
[`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105)). Which of the two errors is reported for
|
||||
this combination depends on the order in which the operands of a comparison are evaluated, so do not rely on it.
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -62,6 +65,10 @@ Unlike [`patch`](patch.md), `patch_inplace` applies the operation "in place" and
|
||||
That makes it faster for large documents by avoiding the copy. However, the JSON value might be corrupted if the
|
||||
function throws an exception.
|
||||
|
||||
Duplicate member names inside an operation object are resolved by the parser before the patch is applied (the last one
|
||||
is kept, see [`object_t`](object_t.md#behavior)), so `#!json {"op": "add", "op": "remove", "path": "/a"}` is a
|
||||
`remove` operation.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: apply a JSON patch in place"
|
||||
@@ -107,6 +114,7 @@ function throws an exception.
|
||||
- Added in version 3.11.0.
|
||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||
target location has a non-object/non-array parent in version 3.13.0.
|
||||
This includes a `null` parent, which was previously silently converted to an object, in version 3.13.0.
|
||||
- Added [`out_of_range.413`](../../home/exceptions.md#jsonexceptionout_of_range413) and stopped silently ignoring a "remove" operation whose target
|
||||
location has a non-object/non-array parent in version 3.13.0.
|
||||
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
||||
|
||||
@@ -36,9 +36,9 @@ The function can throw the following exceptions:
|
||||
- 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"`
|
||||
- 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 begins with a digit but is not a valid array index
|
||||
(such as `1a`), or is `-`; example:
|
||||
`"unresolved reference token '-'"`
|
||||
(because one of its keys is `0`) and another key at that level is empty (as in `/a/`), is `-`, or begins with a digit
|
||||
but is not a valid array index (such as `1a`); examples: `"unresolved reference token '-'"`,
|
||||
`"unresolved reference token ''"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -46,7 +46,7 @@ Linear in the size of the JSON value.
|
||||
|
||||
## Notes
|
||||
|
||||
Empty objects and arrays are flattened by [`flatten()`](flatten.md) to `#!json null` values and cannot unflattened to
|
||||
Empty objects and arrays are flattened by [`flatten()`](flatten.md) to `#!json null` values and cannot be unflattened to
|
||||
their original type.
|
||||
|
||||
A flattened array and a flattened object whose keys are array indices are indistinguishable, because both are
|
||||
@@ -54,7 +54,12 @@ described by the same JSON pointers. A value is therefore restored as an array i
|
||||
reference token `0`, and as an object otherwise: `#!json {"2": 1}` is restored unchanged, whereas `#!json {"0": 1}` is
|
||||
restored as `#!json [1]`. This decision does not depend on the order in which the flattened object is iterated.
|
||||
|
||||
Apart from these two cases, for a JSON value `j`, the following is always true:
|
||||
A third case is an object that has the key `0` next to a key that is not a valid array index: `#!json {"0": 1, "b": 2}`
|
||||
is flattened to `#!json {"/0": 1, "/b": 2}`, and unflatten treats the level as an array and throws
|
||||
[`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) because `b` is not a number. (For the keys
|
||||
`-`, `1a`, or the empty key instead of `b`, it throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404).)
|
||||
|
||||
Apart from these three cases, for a JSON value `j`, the following is always true:
|
||||
`#!cpp j == j.flatten().unflatten()`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -45,6 +45,9 @@ This is equivalent to Python's `dict.get(key, default)`.
|
||||
return default_value;
|
||||
}
|
||||
```
|
||||
with one exception: if the JSON value is neither an array nor an object, the function throws
|
||||
[`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) before looking at `ptr`, even for the empty
|
||||
pointer, whereas `at` returns the value itself for the empty pointer.
|
||||
|
||||
!!! note "Differences to `at` and `operator[]`"
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ Parent of this JSON pointer; in case this JSON pointer is the root, the root its
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this function never throws exceptions.
|
||||
Strong exception safety: if an exception occurs, the original value stays intact. The function is not `#!cpp noexcept`
|
||||
and allocates a new JSON pointer, so it can throw `#!cpp std::bad_alloc`; it throws no library exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ the stream `o`
|
||||
1. Throws [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) if a string stored inside the JSON
|
||||
value is not UTF-8 encoded. Note that unlike the [`dump`](basic_json/dump.md) member functions, no `error_handler`
|
||||
can be set.
|
||||
2. None.
|
||||
2. Throws no library exceptions. As the string representation is built with [`to_string`](json_pointer/to_string.md),
|
||||
`#!cpp std::bad_alloc` is possible.
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -31,6 +31,12 @@ other three continue on its result.
|
||||
If the document is large and the original value is no longer needed,
|
||||
[`patch_inplace`](../api/basic_json/patch_inplace.md) applies the same operations in place instead.
|
||||
|
||||
!!! note "Duplicate member names"
|
||||
|
||||
Duplicate member names inside an operation object are resolved by the parser before the patch is applied (the last
|
||||
one is kept, see [`object_t`](../api/basic_json/object_t.md#behavior)), so
|
||||
`#!json {"op": "add", "op": "remove", "path": "/a"}` is a `remove` operation.
|
||||
|
||||
??? example "Example: apply a JSON Patch"
|
||||
|
||||
The following code shows how a JSON patch is applied to a value.
|
||||
@@ -61,12 +67,23 @@ flowchart LR
|
||||
|
||||
!!! success "Invariant"
|
||||
|
||||
For two JSON values *source* and *target*, the following code yields always true:
|
||||
For two JSON values *source* and *target*, the following code yields true:
|
||||
|
||||
```cpp
|
||||
source.patch(diff(source, target)) == target;
|
||||
```
|
||||
|
||||
The equality holds up to [`operator==`](../api/basic_json/operator_eq.md), with these exceptions:
|
||||
|
||||
- `NaN` and [discarded](../api/basic_json/is_discarded.md) values are not equal to themselves, so the invariant
|
||||
cannot hold for them. `diff` emits a `replace` operation for such a value, and a `NaN` in a patch is serialized
|
||||
as `#!json null`.
|
||||
- Numbers that compare equal produce no operation even if their types differ: `diff(1, 1.0)`, `diff(1u, 1)`, and
|
||||
`diff(0.0, -0.0)` return `#!json []`, so the patched value keeps the number type of *source*.
|
||||
- A [binary value](binary_values.md) in a patch is serialized as an object
|
||||
(`#!json {"bytes":[...],"subtype":null}`), so a patch that was dumped and parsed again no longer holds a binary
|
||||
value.
|
||||
|
||||
??? example "Example: create a JSON Patch from the difference of two values"
|
||||
|
||||
The following code shows how a JSON patch is created as a diff for two JSON values.
|
||||
|
||||
@@ -71,6 +71,10 @@ Then every value inside the JSON document can be identified as follows:
|
||||
Note `/` does not identify the root (i.e., the whole document), but an object entry with empty key `""`. See
|
||||
[RFC 6901](https://tools.ietf.org/html/rfc6901) for more information.
|
||||
|
||||
[RFC 6901, section 4](https://tools.ietf.org/html/rfc6901#section-4) states that evaluation fails if an object has
|
||||
non-unique member names. A `basic_json` object holds one value per key (see [`object_t`](../api/basic_json/object_t.md)
|
||||
for how duplicate keys are handled while parsing), so evaluating a JSON Pointer never encounters duplicates.
|
||||
|
||||
## JSON Pointer creation
|
||||
|
||||
JSON Pointers can be created from a string:
|
||||
@@ -88,6 +92,13 @@ auto p = "/nested/one"_json_pointer;
|
||||
The escaping rules of [RFC 6901](https://tools.ietf.org/html/rfc6901) are implemented. See the
|
||||
[constructor documentation](../api/json_pointer/json_pointer.md) for more information.
|
||||
|
||||
!!! note "URI fragment representation"
|
||||
|
||||
[RFC 6901, section 6](https://tools.ietf.org/html/rfc6901#section-6) also defines a URI fragment identifier
|
||||
representation (`#/a%20b`). It is not supported: `#!cpp json::json_pointer("#/a")` throws
|
||||
[`parse_error.107`](../home/exceptions.md#jsonexceptionparse_error107). Strip the leading `#` and
|
||||
percent-decode the remainder before creating the JSON pointer.
|
||||
|
||||
## Value access
|
||||
|
||||
JSON Pointers can be used in the [`at`](../api/basic_json/at.md), [`operator[]`](../api/basic_json/operator%5B%5D.md),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The library supports JSON Merge Patch ([RFC 7396](https://tools.ietf.org/html/rfc7396)) as a patch format.
|
||||
The merge patch format is primarily intended for use with the HTTP PATCH method as a means of describing a set of
|
||||
modifications to a target resource's content. This function applies a merge patch to the current JSON value.
|
||||
modifications to a target resource's content. Applying a merge patch changes the JSON value the patch is applied to.
|
||||
|
||||
Instead of using [JSON Pointer](json_pointer.md) to specify values to be manipulated, it describes the changes using a
|
||||
syntax that closely mimics the document being modified. Unlike [JSON Patch](json_patch.md), a JSON Merge Patch cannot
|
||||
@@ -48,6 +48,18 @@ flowchart LR
|
||||
[`update`](../api/basic_json/update.md) with `merge_objects` set to `#!cpp true`; see
|
||||
[Merging objects](modifying_values.md#merging-objects).
|
||||
|
||||
!!! note "Limitations of RFC 7396"
|
||||
|
||||
- A patch cannot set a member to `#!json null`, because `#!json null` removes the member:
|
||||
`#!json {"a":1}` patched with `#!json {"a":null}` gives `#!json {}`.
|
||||
- Arrays are replaced as a whole, never merged, and a `#!json null` inside an array is kept.
|
||||
- `#!json null` members of the target that the patch does not mention are preserved.
|
||||
- A `#!json null` that would remove a member of a not yet existing object still creates that object:
|
||||
`#!json {}` patched with `#!json {"a":{"b":null}}` gives `#!json {"a":{}}`.
|
||||
- A patch that is not an object replaces the whole target (a `#!json null` patch makes the target
|
||||
`#!json null`); an object patch applied to a non-object target starts from an empty object.
|
||||
- [`merge_diff`](../api/basic_json/merge_diff.md#notes) has a matching limitation for `#!json null` members.
|
||||
|
||||
??? example
|
||||
|
||||
The following code shows how a JSON Merge Patch is applied to a JSON document.
|
||||
|
||||
@@ -390,6 +390,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
||||
described in RFC 6901. Neither `find(const StringType&, size_type)`, nor `substr(pos, count)`, nor
|
||||
`replace(pos, count, const StringType&)` is required.
|
||||
- `empty()`.
|
||||
- `resize(n)` (one argument) -- used by `to_string` to size the result before the reference tokens are copied into it.
|
||||
- `begin()` and `end()` -- used by
|
||||
[`operator[](const json_pointer&)`](../../api/basic_json/operator%5B%5D.md) to decide whether a reference token
|
||||
denotes an array index.
|
||||
|
||||
@@ -1083,9 +1083,14 @@ a JSON pointer exceeds the range of `size_type` (e.g., on 32-bit platforms).
|
||||
|
||||
```
|
||||
enum value out of range
|
||||
array index 18446744073709551616 exceeds size_type
|
||||
array index 18446744073709551615 exceeds size_type
|
||||
```
|
||||
|
||||
The second message is thrown, for instance, by `#!cpp json::parse("[1, 2]").at("/18446744073709551615"_json_pointer)`
|
||||
on a 64-bit platform, where `size_type` is `#!cpp std::size_t` and this index is `SIZE_MAX`. An index that does not
|
||||
fit into 64 bits (such as `18446744073709551616`) is not reported as 410 but as
|
||||
[`out_of_range.404`](#jsonexceptionout_of_range404).
|
||||
|
||||
### json.exception.out_of_range.411
|
||||
|
||||
A JSON Patch `add` operation cannot be applied because the target location's parent is neither an object nor an array. Per [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902), an `add` target must reference a member of an existing object or an element of an existing array; a primitive value (string, number, boolean, etc.) cannot receive a new member or element.
|
||||
@@ -1100,6 +1105,8 @@ A JSON Patch `add` operation cannot be applied because the target location's par
|
||||
|
||||
This exception was added in version 3.13.0. Before that, this situation hit an internal assertion (aborting the program in debug builds) or was silently ignored when assertions were disabled.
|
||||
|
||||
A `null` parent is rejected as well. Before version 3.13.0, an `add` into a `null` parent silently converted it to an object (e.g., `add` at `/foo/bar` turned `{"foo":null}` into `{"foo":{"bar":1}}`).
|
||||
|
||||
### json.exception.out_of_range.412
|
||||
|
||||
BSON stores the length of documents, arrays, strings, and binary values in a signed 32-bit integer, and MessagePack
|
||||
|
||||
Reference in new issue
Block a user