From 9225cf2f572df13027e67bda5b188ae6d2702605 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 15 Jan 2019 14:39:06 +0100 Subject: [PATCH] allow push_back() and pop_back() calls on json_pointer Putting pop_back() to public and creating a trivial push_back() method allows users of nlohmann::json_pointer to manipulate an existing json-pointer by adding or removing keys at the end. This is useful for traversing a JSON-instance and keeping track of its "absolute path" at any moment. In my case for a schema-validator error-handler. --- include/nlohmann/detail/json_pointer.hpp | 11 ++++- single_include/nlohmann/json.hpp | 11 ++++- test/src/unit-json_pointer.cpp | 54 ++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 3521b889db..033625bc4c 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -97,7 +97,6 @@ class json_pointer return res; } - private: /*! @brief remove and return last reference pointer @throw out_of_range.405 if JSON pointer has no parent @@ -114,6 +113,16 @@ class json_pointer return last; } + /*! + @brief remove and return last reference pointer + @throw out_of_range.405 if JSON pointer has no parent + */ + void push_back(const std::string& tok) + { + reference_tokens.push_back(tok); + } + + private: /// return whether pointer points to the root document bool is_root() const noexcept { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 70b6c8a855..e3b54c88f6 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -11885,7 +11885,6 @@ class json_pointer return res; } - private: /*! @brief remove and return last reference pointer @throw out_of_range.405 if JSON pointer has no parent @@ -11902,6 +11901,16 @@ class json_pointer return last; } + /*! + @brief remove and return last reference pointer + @throw out_of_range.405 if JSON pointer has no parent + */ + void push_back(const std::string& tok) + { + reference_tokens.push_back(tok); + } + + private: /// return whether pointer points to the root document bool is_root() const noexcept { diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index ac9cd71e2a..1bcd3938a7 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -459,4 +459,58 @@ TEST_CASE("JSON pointers") CHECK(j.is_object()); } } + + SECTION("push and pop") + { + const json j = + { + {"", "Hello"}, + {"pi", 3.141}, + {"happy", true}, + {"name", "Niels"}, + {"nothing", nullptr}, + { + "answer", { + {"everything", 42} + } + }, + {"list", {1, 0, 2}}, + { + "object", { + {"currency", "USD"}, + {"value", 42.99}, + {"", "empty string"}, + {"/", "slash"}, + {"~", "tilde"}, + {"~1", "tilde1"} + } + } + }; + + // empty json_pointer returns the root JSON-object + auto ptr = ""_json_pointer; + CHECK(j[ptr] == j); + + // simple field access + ptr.push_back("pi"); + CHECK(j[ptr] == j["pi"]); + + ptr.pop_back(); + CHECK(j[ptr] == j); + + // object and children access + ptr.push_back("answer"); + ptr.push_back("everything"); + CHECK(j[ptr] == j["answer"]["everything"]); + + ptr.pop_back(); + ptr.pop_back(); + CHECK(j[ptr] == j); + + // push key which has to be encoded + ptr.push_back("object"); + ptr.push_back("/"); + CHECK(j[ptr] == j["object"]["/"]); + CHECK(ptr.to_string() == "/object/~1"); + } }