From fa9a1395c804bfd5f7e3d779b5afa84696eb2b10 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Sat, 16 Jul 2022 06:47:10 -0500 Subject: [PATCH 1/3] add patch_inplace function to json class --- docs/mkdocs/docs/api/basic_json/patch.md | 13 +++++++++++-- include/nlohmann/json.hpp | 16 ++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/mkdocs/docs/api/basic_json/patch.md b/docs/mkdocs/docs/api/basic_json/patch.md index b3ef963f04..ce4574f2f9 100644 --- a/docs/mkdocs/docs/api/basic_json/patch.md +++ b/docs/mkdocs/docs/api/basic_json/patch.md @@ -1,13 +1,20 @@ # nlohmann::basic_json::patch ```cpp +// (1) basic_json patch(const basic_json& json_patch) const; + +// (2) +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. +1. applies a JSON patch to a copy of the current object and returns the copy +2. applies a JSON patch in place and returns void + ## Parameters `json_patch` (in) @@ -15,11 +22,13 @@ the patch. ## Return value -patched document +1. patched document +2. void ## Exception safety -Strong guarantee: if an exception is thrown, there are no changes in the JSON value. +1. Strong guarantee: if an exception is thrown, there are no changes in the JSON value. +2. No guarantees, value may be corruted. ## Exceptions diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index c8a71e2598..c41f4585b1 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -4641,13 +4641,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}; @@ -4911,7 +4909,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; } @@ -5049,7 +5054,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } - /// @} //////////////////////////////// From fd626200053c6fb1055bfeb0d6b8f711442382cc Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Wed, 20 Jul 2022 14:43:19 +0200 Subject: [PATCH 2/3] add documentation --- docs/examples/patch_inplace.cpp | 34 ++++++++++ docs/examples/patch_inplace.output | 13 ++++ docs/mkdocs/docs/api/basic_json/patch.md | 13 +--- .../docs/api/basic_json/patch_inplace.md | 66 +++++++++++++++++++ single_include/nlohmann/json.hpp | 16 +++-- 5 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 docs/examples/patch_inplace.cpp create mode 100644 docs/examples/patch_inplace.output create mode 100644 docs/mkdocs/docs/api/basic_json/patch_inplace.md diff --git a/docs/examples/patch_inplace.cpp b/docs/examples/patch_inplace.cpp new file mode 100644 index 0000000000..62bc527d84 --- /dev/null +++ b/docs/examples/patch_inplace.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +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; +} diff --git a/docs/examples/patch_inplace.output b/docs/examples/patch_inplace.output new file mode 100644 index 0000000000..9d31b8ba47 --- /dev/null +++ b/docs/examples/patch_inplace.output @@ -0,0 +1,13 @@ +Before +{ + "baz": "qux", + "foo": "bar" +} + +After +{ + "baz": "boo", + "hello": [ + "world" + ] +} diff --git a/docs/mkdocs/docs/api/basic_json/patch.md b/docs/mkdocs/docs/api/basic_json/patch.md index ce4574f2f9..b3ef963f04 100644 --- a/docs/mkdocs/docs/api/basic_json/patch.md +++ b/docs/mkdocs/docs/api/basic_json/patch.md @@ -1,20 +1,13 @@ # nlohmann::basic_json::patch ```cpp -// (1) basic_json patch(const basic_json& json_patch) const; - -// (2) -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. -1. applies a JSON patch to a copy of the current object and returns the copy -2. applies a JSON patch in place and returns void - ## Parameters `json_patch` (in) @@ -22,13 +15,11 @@ the patch. ## Return value -1. patched document -2. void +patched document ## Exception safety -1. Strong guarantee: if an exception is thrown, there are no changes in the JSON value. -2. No guarantees, value may be corruted. +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. ## Exceptions diff --git a/docs/mkdocs/docs/api/basic_json/patch_inplace.md b/docs/mkdocs/docs/api/basic_json/patch_inplace.md new file mode 100644 index 0000000000..1b95304d29 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/patch_inplace.md @@ -0,0 +1,66 @@ +# nlohmann::basic_json::patch + +```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 + +## Return value + +void + +## 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_inplace` applies the operation "in place" and no copy of the json document is created. That makes it faster for large documents by avoiding the copy. However, the value of the json document 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) +- [merge_patch](merge_patch.md) applies a JSON Merge Patch diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index cffbd7dce9..271a83a5c5 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -23158,13 +23158,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}; @@ -23428,7 +23426,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; } @@ -23566,7 +23571,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } - /// @} //////////////////////////////// From fe31d31a1b3c755601f7c804daf5778718bca086 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 21 Jul 2022 08:48:02 +0200 Subject: [PATCH 3/3] fix up docs --- docs/mkdocs/docs/api/basic_json/patch.md | 1 + docs/mkdocs/docs/api/basic_json/patch_inplace.md | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/mkdocs/docs/api/basic_json/patch.md b/docs/mkdocs/docs/api/basic_json/patch.md index b3ef963f04..deec47434c 100644 --- a/docs/mkdocs/docs/api/basic_json/patch.md +++ b/docs/mkdocs/docs/api/basic_json/patch.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/patch_inplace.md b/docs/mkdocs/docs/api/basic_json/patch_inplace.md index 1b95304d29..0b2055db26 100644 --- a/docs/mkdocs/docs/api/basic_json/patch_inplace.md +++ b/docs/mkdocs/docs/api/basic_json/patch_inplace.md @@ -1,4 +1,4 @@ -# nlohmann::basic_json::patch +# nlohmann::basic_json::patch_inplace ```cpp void patch_inplace(const basic_json& json_patch) const; @@ -12,10 +12,6 @@ a JSON document. With this function, a JSON Patch is applied to the current JSON `json_patch` (in) : JSON patch document -## Return value - -void - ## Exception safety No guarantees, value may be corrupted by an unsuccessful patch operation. @@ -41,7 +37,7 @@ affected by the patch, the complexity can usually be neglected. ## Notes -Unlike `patch`, `patch_inplace` applies the operation "in place" and no copy of the json document is created. That makes it faster for large documents by avoiding the copy. However, the value of the json document might be corrupted if the function throws an exception. +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 @@ -63,4 +59,5 @@ Unlike `patch`, `patch_inplace` applies the operation "in place" and no copy of - [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