Skip to content

Commit

Permalink
add patch_inplace function (#3581)
Browse files Browse the repository at this point in the history
* add patch_inplace function to json class

* add documentation

* fix up docs
  • Loading branch information
wolfv authored Jul 21, 2022
1 parent 4b6d363 commit 09fb481
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 12 deletions.
34 changes: 34 additions & 0 deletions docs/examples/patch_inplace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
// the original document
json doc = R"(
{
"baz": "qux",
"foo": "bar"
}
)"_json;

// the patch
json patch = R"(
[
{ "op": "replace", "path": "/baz", "value": "boo" },
{ "op": "add", "path": "/hello", "value": ["world"] },
{ "op": "remove", "path": "/foo"}
]
)"_json;

// output original document
std::cout << "Before\n" << std::setw(4) << doc << std::endl;

// apply the patch
doc.patch_inplace(patch);

// output patched document
std::cout << "After\n" << std::setw(4) << doc << std::endl;
}
13 changes: 13 additions & 0 deletions docs/examples/patch_inplace.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Before
{
"baz": "qux",
"foo": "bar"
}

After
{
"baz": "boo",
"hello": [
"world"
]
}
1 change: 1 addition & 0 deletions docs/mkdocs/docs/api/basic_json/patch.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ is thrown. In any case, the original value is not changed: the patch is applied
- [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
- [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
- [patch_inplace](patch_inplace.md) applies a JSON Patch without creating a copy of the document
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
## Version history
Expand Down
63 changes: 63 additions & 0 deletions docs/mkdocs/docs/api/basic_json/patch_inplace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# <small>nlohmann::basic_json::</small>patch_inplace

```cpp
void patch_inplace(const basic_json& json_patch) const;
```
[JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to
a JSON document. With this function, a JSON Patch is applied to the current JSON value by executing all operations from the patch. This function applies a JSON patch in place and returns void.
## Parameters
`json_patch` (in)
: JSON patch document
## Exception safety
No guarantees, value may be corrupted by an unsuccessful patch operation.
## Exceptions
- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of
an array of objects.
- 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"`.
- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index 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"`.
- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent
("add", "remove", "move")
- Throws [`out_of_range.501`](../../home/exceptions.md#jsonexceptionother_error501) if "test" operation was
unsuccessful.
## Complexity
Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is
affected by the patch, the complexity can usually be neglected.
## Notes
Unlike [`patch`](patch.md), `patch_inplace` applies the operation "in place" and no copy of the JSON value is created. That makes it faster for large documents by avoiding the copy. However, the JSON value might be corrupted if the function throws an exception.
## Examples
??? example
The following code shows how a JSON patch is applied to a value.
```cpp
--8<-- "examples/patch_inplace.cpp"
```
Output:
```json
--8<-- "examples/patch_inplace.output"
```
## See also
- [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
- [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
- [patch](patch.md) applies a JSON Merge Patch
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
16 changes: 10 additions & 6 deletions include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4620,13 +4620,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @name JSON Patch functions
/// @{

/// @brief applies a JSON patch
/// @brief applies a JSON patch in-place without copying the object
/// @sa https://json.nlohmann.me/api/basic_json/patch/
basic_json patch(const basic_json& json_patch) const
void patch_inplace(const basic_json& json_patch)
{
// make a working copy to apply the patch to
basic_json result = *this;

basic_json& result = *this;
// the valid JSON Patch operations
enum class patch_operations {add, remove, replace, move, copy, test, invalid};

Expand Down Expand Up @@ -4890,7 +4888,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
}
}
}

/// @brief applies a JSON patch to a copy of the current object
/// @sa https://json.nlohmann.me/api/basic_json/patch/
basic_json patch(const basic_json& json_patch) const
{
basic_json result = *this;
result.patch_inplace(json_patch);
return result;
}

Expand Down Expand Up @@ -5028,7 +5033,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec

return result;
}

/// @}

////////////////////////////////
Expand Down
16 changes: 10 additions & 6 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23445,13 +23445,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @name JSON Patch functions
/// @{

/// @brief applies a JSON patch
/// @brief applies a JSON patch in-place without copying the object
/// @sa https://json.nlohmann.me/api/basic_json/patch/
basic_json patch(const basic_json& json_patch) const
void patch_inplace(const basic_json& json_patch)
{
// make a working copy to apply the patch to
basic_json result = *this;

basic_json& result = *this;
// the valid JSON Patch operations
enum class patch_operations {add, remove, replace, move, copy, test, invalid};

Expand Down Expand Up @@ -23715,7 +23713,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
}
}
}

/// @brief applies a JSON patch to a copy of the current object
/// @sa https://json.nlohmann.me/api/basic_json/patch/
basic_json patch(const basic_json& json_patch) const
{
basic_json result = *this;
result.patch_inplace(json_patch);
return result;
}

Expand Down Expand Up @@ -23853,7 +23858,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec

return result;
}

/// @}

////////////////////////////////
Expand Down

0 comments on commit 09fb481

Please sign in to comment.