From a06e7f5d80af9b5a97f4a3ddcc25dd97c0b1d9dc Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Thu, 24 Jan 2019 16:46:51 +0100 Subject: [PATCH] JSON-pointer: add operator+() returning a new json_pointer --- include/nlohmann/detail/json_pointer.hpp | 23 +++++++++- single_include/nlohmann/json.hpp | 23 +++++++++- test/src/unit-json_pointer.cpp | 54 ++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 033625bc..705346c5 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -114,14 +114,33 @@ class json_pointer } /*! - @brief remove and return last reference pointer - @throw out_of_range.405 if JSON pointer has no parent + @brief append a token at the end of the reference pointer */ void push_back(const std::string& tok) { reference_tokens.push_back(tok); } + /*! + @brief append a key-token at the end of the reference pointer and return a new json-pointer. + */ + json_pointer operator+(const std::string& tok) const + { + auto ptr = *this; + ptr.push_back(tok); + return ptr; + } + + /*! + @brief append a array-index-token at the end of the reference pointer and return a new json-pointer. + */ + json_pointer operator+(const size_t& index) const + { + auto ptr = *this; + ptr.push_back(std::to_string(index)); + return ptr; + } + 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 ee72531b..d845f77e 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -11924,14 +11924,33 @@ class json_pointer } /*! - @brief remove and return last reference pointer - @throw out_of_range.405 if JSON pointer has no parent + @brief append a token at the end of the reference pointer */ void push_back(const std::string& tok) { reference_tokens.push_back(tok); } + /*! + @brief append a key-token at the end of the reference pointer and return a new json-pointer. + */ + json_pointer operator+(const std::string& tok) const + { + auto ptr = *this; + ptr.push_back(tok); + return ptr; + } + + /*! + @brief append a array-index-token at the end of the reference pointer and return a new json-pointer. + */ + json_pointer operator+(const size_t& index) const + { + auto ptr = *this; + ptr.push_back(std::to_string(index)); + return ptr; + } + 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 1bcd3938..373b2c21 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -513,4 +513,58 @@ TEST_CASE("JSON pointers") CHECK(j[ptr] == j["object"]["/"]); CHECK(ptr.to_string() == "/object/~1"); } + + SECTION("operators") + { + 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 = ptr + "pi"; + CHECK(j[ptr] == j["pi"]); + + ptr.pop_back(); + CHECK(j[ptr] == j); + + // object and children access + ptr = ptr + "answer"; + ptr = ptr + "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 = ptr + "object"; + ptr = ptr + "/"; + CHECK(j[ptr] == j["object"]["/"]); + CHECK(ptr.to_string() == "/object/~1"); + } }