diff --git a/ChangeLog.md b/ChangeLog.md index 0acd10f5..75827603 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,10 +5,12 @@ All notable changes to this project will be documented in this file. This projec [Full Changelog](https://github.com/nlohmann/json/compare/v1.1.0...HEAD) +- Additional integration options [\#237](https://github.com/nlohmann/json/issues/237) +- Can't use basic\_json::iterator as a base iterator for std::move\_iterator [\#233](https://github.com/nlohmann/json/issues/233) - Provide a FAQ [\#163](https://github.com/nlohmann/json/issues/163) - Create PULL\_REQUEST\_TEMPLATE.md [\#213](https://github.com/nlohmann/json/pull/213) ([whackashoe](https://github.com/whackashoe)) - fixed noexcept; added constexpr [\#208](https://github.com/nlohmann/json/pull/208) ([nlohmann](https://github.com/nlohmann)) -- Add support for afl-fuzz testing [\#207](https://github.com/nlohmann/json/pull/207) ([msm-](https://github.com/msm-)) +- Add support for afl-fuzz testing [\#207](https://github.com/nlohmann/json/pull/207) ([mykter](https://github.com/mykter)) - Issue \#178 - Extending support to full uint64\_t/int64\_t range and unsigned type \(updated\) [\#193](https://github.com/nlohmann/json/pull/193) ([twelsby](https://github.com/twelsby)) - double values are serialized with commas as decimal points [\#228](https://github.com/nlohmann/json/issues/228) @@ -26,6 +28,7 @@ All notable changes to this project will be documented in this file. This projec - Conflicting typedef of ssize\_t on Windows 32 bit when using Boost.Python [\#204](https://github.com/nlohmann/json/issues/204) - Integer conversion to unsigned [\#178](https://github.com/nlohmann/json/issues/178) +- Implement additional integration options [\#238](https://github.com/nlohmann/json/pull/238) ([robertmrk](https://github.com/robertmrk)) - make serialization locale-independent [\#232](https://github.com/nlohmann/json/pull/232) ([nlohmann](https://github.com/nlohmann)) - fixes \#223 by updating README.md [\#227](https://github.com/nlohmann/json/pull/227) ([kevin--](https://github.com/kevin--)) - Use namespace std for int64\_t and uint64\_t [\#226](https://github.com/nlohmann/json/pull/226) ([lv-zheng](https://github.com/lv-zheng)) diff --git a/doc/examples/json_pointer__to_string.cpp b/doc/examples/json_pointer__to_string.cpp new file mode 100644 index 00000000..4cb053c5 --- /dev/null +++ b/doc/examples/json_pointer__to_string.cpp @@ -0,0 +1,34 @@ +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON Pointers + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + json::json_pointer ptr3("/foo/0"); + json::json_pointer ptr4("/"); + json::json_pointer ptr5("/a~1b"); + json::json_pointer ptr6("/c%d"); + json::json_pointer ptr7("/e^f"); + json::json_pointer ptr8("/g|h"); + json::json_pointer ptr9("/i\\j"); + json::json_pointer ptr10("/k\"l"); + json::json_pointer ptr11("/ "); + json::json_pointer ptr12("/m~0n"); + + + std::cout << ptr1.to_string() << '\n' + << ptr2.to_string() << '\n' + << ptr3.to_string() << '\n' + << ptr4.to_string() << '\n' + << ptr5.to_string() << '\n' + << ptr6.to_string() << '\n' + << ptr7.to_string() << '\n' + << ptr8.to_string() << '\n' + << ptr9.to_string() << '\n' + << ptr10.to_string() << '\n' + << ptr11.to_string() << '\n' + << ptr12.to_string() << std::endl; +} diff --git a/doc/examples/json_pointer__to_string.link b/doc/examples/json_pointer__to_string.link new file mode 100644 index 00000000..407609b2 --- /dev/null +++ b/doc/examples/json_pointer__to_string.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/json_pointer__to_string.output b/doc/examples/json_pointer__to_string.output new file mode 100644 index 00000000..c4b5ea8f --- /dev/null +++ b/doc/examples/json_pointer__to_string.output @@ -0,0 +1,12 @@ + +/foo +/foo/0 +/ +/a~1b +/c%d +/e^f +/g|h +/i\j +/k"l +/ +/m~0n diff --git a/src/json.hpp b/src/json.hpp index 1785f182..6b22e89d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8818,6 +8818,10 @@ basic_json_parser_63: /*! @brief JSON Pointer + A JSON pointer defines a string syntax for identifying a specific value + within a JSON document. It can be used with functions `at` and + `operator[]`. Furthermore, JSON pointers are the base for JSON patches. + @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) @since version 2.0.0 @@ -8854,10 +8858,37 @@ basic_json_parser_63: : reference_tokens(split(s)) {} - /// test for inequality - bool operator!=(const json_pointer& rhs) const + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`., + json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const noexcept { - return reference_tokens != rhs.reference_tokens; + std::string result; + + for (const auto& reference_token : reference_tokens) + { + result += "/" + escape(reference_token); + } + + return result; + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); } private: diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 51b72167..3dab33bb 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8128,6 +8128,10 @@ class basic_json /*! @brief JSON Pointer + A JSON pointer defines a string syntax for identifying a specific value + within a JSON document. It can be used with functions `at` and + `operator[]`. Furthermore, JSON pointers are the base for JSON patches. + @sa [RFC 6901](https://tools.ietf.org/html/rfc6901) @since version 2.0.0 @@ -8164,10 +8168,37 @@ class basic_json : reference_tokens(split(s)) {} - /// test for inequality - bool operator!=(const json_pointer& rhs) const + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`., + json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const noexcept { - return reference_tokens != rhs.reference_tokens; + std::string result; + + for (const auto& reference_token : reference_tokens) + { + result += "/" + escape(reference_token); + } + + return result; + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); } private: diff --git a/test/unit.cpp b/test/unit.cpp index f6c49883..d038b867 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -12035,6 +12035,36 @@ TEST_CASE("Unicode", "[hide]") // the array has 1112064 + 1 elemnts (a terminating "null" value) CHECK(j.size() == 1112065); + + SECTION("check JSON Pointers") + { + for (auto s : j) + { + // skip non-string JSON values + if (not s.is_string()) + { + continue; + } + + std::string ptr = s; + + // tilde must be followed by 0 or 1 + if (ptr == "~") + { + ptr += "0"; + } + + // JSON Pointers must begin with "/" + ptr = "/" + ptr; + + CHECK_NOTHROW(json::json_pointer("/" + ptr)); + + // check escape/unescape roundtrip + auto escaped = json::json_pointer::escape(ptr); + json::json_pointer::unescape(escaped); + CHECK(escaped == ptr); + } + } } SECTION("ignore byte-order-mark") @@ -12389,6 +12419,17 @@ TEST_CASE("JSON pointers") json j_object(json::value_t::object); CHECK(j_object.flatten().unflatten() == json()); } + + SECTION("string representation") + { + for (auto ptr : + {"", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n" + }) + { + CHECK(json::json_pointer(ptr).to_string() == ptr); + CHECK(json::json_pointer(ptr) == ptr); + } + } } TEST_CASE("JSON patch")