From 397ada22d35cf2ebc168a48f264218c069f13d74 Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Wed, 20 Apr 2016 16:52:00 +0200
Subject: [PATCH] implemented remove

---
 src/json.hpp      | 26 +++++++++++++++++++++++--
 src/json.hpp.re2c | 26 +++++++++++++++++++++++--
 test/unit.cpp     | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index acde03bf..de6c6ec1 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -8969,6 +8969,18 @@ basic_json_parser_63:
             : reference_tokens(split(s))
         {}
 
+        std::string pop_back()
+        {
+            if (reference_tokens.empty())
+            {
+                throw std::domain_error("JSON pointer has no parent");
+            }
+
+            auto last = reference_tokens.back();
+            reference_tokens.pop_back();
+            return last;
+        }
+
       private:
         /*!
         @brief create and return a reference to the pointed to value
@@ -9420,7 +9432,7 @@ basic_json_parser_63:
 
       private:
         /// the reference tokens
-        const std::vector<std::string> reference_tokens {};
+        std::vector<std::string> reference_tokens {};
     };
 
     ////////////////////////////
@@ -9539,7 +9551,7 @@ basic_json_parser_63:
 
             const std::string op = it_op->second;
             const std::string path = it_path->second;
-            const json_pointer ptr(path);
+            json_pointer ptr(path);
 
             if (op == "add")
             {
@@ -9552,6 +9564,16 @@ basic_json_parser_63:
             }
             else if (op == "remove")
             {
+                const auto last_path = ptr.pop_back();
+                basic_json& parent = result.at(ptr);
+                if (parent.is_object())
+                {
+                    parent.erase(parent.find(last_path));
+                }
+                else if (parent.is_array())
+                {
+                    parent.erase(parent.begin() + std::stoi(last_path));
+                }
             }
             else if (op == "replace")
             {
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index d161f38d..073baf36 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -8279,6 +8279,18 @@ class basic_json
             : reference_tokens(split(s))
         {}
 
+        std::string pop_back()
+        {
+            if (reference_tokens.empty())
+            {
+                throw std::domain_error("JSON pointer has no parent");
+            }
+
+            auto last = reference_tokens.back();
+            reference_tokens.pop_back();
+            return last;
+        }
+
       private:
         /*!
         @brief create and return a reference to the pointed to value
@@ -8730,7 +8742,7 @@ class basic_json
 
       private:
         /// the reference tokens
-        const std::vector<std::string> reference_tokens {};
+        std::vector<std::string> reference_tokens {};
     };
 
     ////////////////////////////
@@ -8849,7 +8861,7 @@ class basic_json
 
             const std::string op = it_op->second;
             const std::string path = it_path->second;
-            const json_pointer ptr(path);
+            json_pointer ptr(path);
 
             if (op == "add")
             {
@@ -8862,6 +8874,16 @@ class basic_json
             }
             else if (op == "remove")
             {
+                const auto last_path = ptr.pop_back();
+                basic_json& parent = result.at(ptr);
+                if (parent.is_object())
+                {
+                    parent.erase(parent.find(last_path));
+                }
+                else if (parent.is_array())
+                {
+                    parent.erase(parent.begin() + std::stoi(last_path));
+                }
             }
             else if (op == "replace")
             {
diff --git a/test/unit.cpp b/test/unit.cpp
index 7b675462..6f9ad8f5 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -12421,6 +12421,55 @@ TEST_CASE("JSON patch")
             CHECK(doc.apply_patch(patch) == expected);
         }
 
+        SECTION("example A.3 - Removing an Object Member")
+        {
+            // An example target JSON document:
+            json doc = R"(
+                {
+                    "baz": "qux",
+                    "foo": "bar"
+                }
+            )"_json;
+
+            // A JSON Patch document:
+            json patch = R"(
+                [
+                    { "op": "remove", "path": "/baz" }
+                ]
+            )"_json;
+
+            // The resulting JSON document:
+            json expected = R"(
+                { "foo": "bar" }
+            )"_json;
+
+            // check if patched value is as expected
+            CHECK(doc.apply_patch(patch) == expected);
+        }
+
+        SECTION("example A.4 - Removing an Array Element")
+        {
+            // An example target JSON document:
+            json doc = R"(
+                { "foo": [ "bar", "qux", "baz" ] }
+            )"_json;
+
+            // A JSON Patch document:
+            json patch = R"(
+                [
+                    { "op": "remove", "path": "/foo/1" }
+                ]
+            )"_json;
+
+            // The resulting JSON document:
+            json expected = R"(
+                { "foo": [ "bar", "baz" ] }
+            )"_json;
+
+            // check if patched value is as expected
+            CHECK(doc.apply_patch(patch) == expected);
+        }
+
         SECTION("example A.5 - Replacing a Value")
         {
             // An example target JSON document: