diff --git a/docs/mkdocs/docs/api/operator_literal_json.md b/docs/mkdocs/docs/api/operator_literal_json.md index a3a4bd28b..fdf6e8369 100644 --- a/docs/mkdocs/docs/api/operator_literal_json.md +++ b/docs/mkdocs/docs/api/operator_literal_json.md @@ -2,6 +2,7 @@ ```cpp json operator ""_json(const char* s, std::size_t n); +json operator ""_json(const char8_t* s, std::size_t n); // since C++20 ``` This operator implements a user-defined string literal for JSON objects. It can be used by adding `#!cpp _json` to a @@ -59,3 +60,4 @@ Linear. - Added in version 1.0.0. - Moved to namespace `nlohmann::literals::json_literals` in 3.11.0. +- Added `char8_t*` overload in 3.12.1. diff --git a/docs/mkdocs/docs/api/operator_literal_json_pointer.md b/docs/mkdocs/docs/api/operator_literal_json_pointer.md index 423678c77..2c3d6a13a 100644 --- a/docs/mkdocs/docs/api/operator_literal_json_pointer.md +++ b/docs/mkdocs/docs/api/operator_literal_json_pointer.md @@ -2,6 +2,7 @@ ```cpp json_pointer operator ""_json_pointer(const char* s, std::size_t n); +json_pointer operator ""_json_pointer(const char8_t* s, std::size_t n); // since C++20 ``` This operator implements a user-defined string literal for JSON Pointers. It can be used by adding `#!cpp _json_pointer` @@ -62,3 +63,4 @@ Linear. - Added in version 2.0.0. - Moved to namespace `nlohmann::literals::json_literals` in 3.11.0. +- Added `char8_t*` overload in 3.12.1. diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index e0dd53335..d4502a5c9 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5283,6 +5283,15 @@ JSON_HEDLEY_NON_NULL(1) return nlohmann::json::parse(s, s + n); } +#if defined(__cpp_char8_t) +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator""_json(const char8_t* s, std::size_t n) +{ + return nlohmann::json::parse(reinterpret_cast(s), + reinterpret_cast(s) + n); +} +#endif + /// @brief user-defined string literal for JSON pointer /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ JSON_HEDLEY_NON_NULL(1) @@ -5296,6 +5305,13 @@ JSON_HEDLEY_NON_NULL(1) return nlohmann::json::json_pointer(std::string(s, n)); } +#if defined(__cpp_char8_t) +inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(reinterpret_cast(s), n)); +} +#endif + } // namespace json_literals } // namespace literals NLOHMANN_JSON_NAMESPACE_END diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2a1333881..ceb7a9f11 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -25402,6 +25402,15 @@ JSON_HEDLEY_NON_NULL(1) return nlohmann::json::parse(s, s + n); } +#if defined(__cpp_char8_t) +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator""_json(const char8_t* s, std::size_t n) +{ + return nlohmann::json::parse(reinterpret_cast(s), + reinterpret_cast(s) + n); +} +#endif + /// @brief user-defined string literal for JSON pointer /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ JSON_HEDLEY_NON_NULL(1) @@ -25415,6 +25424,13 @@ JSON_HEDLEY_NON_NULL(1) return nlohmann::json::json_pointer(std::string(s, n)); } +#if defined(__cpp_char8_t) +inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(reinterpret_cast(s), n)); +} +#endif + } // namespace json_literals } // namespace literals NLOHMANN_JSON_NAMESPACE_END diff --git a/tests/src/unit-deserialization.cpp b/tests/src/unit-deserialization.cpp index 78b07f11f..1ed0d2e0f 100644 --- a/tests/src/unit-deserialization.cpp +++ b/tests/src/unit-deserialization.cpp @@ -19,6 +19,11 @@ using nlohmann::json; #include #include +#if defined(_WIN32) + #define NOMINMAX + #include // for GetACP() +#endif + namespace { struct SaxEventLogger : public nlohmann::json_sax @@ -213,6 +218,20 @@ class proxy_iterator private: iterator* m_it = nullptr; }; + +// JSON_HAS_CPP_20 +#if defined(__cpp_char8_t) +bool check_utf8() +{ +#if defined(_WIN32) + // Runtime check of the active ANSI code page + // 65001 == UTF-8 + return GetACP() == 65001; +#else + return true; +#endif +} +#endif } // namespace TEST_CASE("deserialization") @@ -1132,6 +1151,31 @@ TEST_CASE("deserialization") CHECK(object_count == 4); } } + + // build with C++20 + // JSON_HAS_CPP_20 +#if defined(__cpp_char8_t) + SECTION("Using _json with char8_t literals #4945") + { + // Regular narrow string literal + const auto j1 = R"({"key": "value", "num": 42})"_json; + CHECK(j1["key"] == "value"); + CHECK(j1["num"] == 42); + + // UTF-8 prefixed literal (C++20 and later); + // MSVC may not set /utf-8, so we need to check + if (check_utf8()) + { + const auto j2 = u8R"({"emoji": "😀", "msg": "hello"})"_json; + CHECK(j2["emoji"] == "😀"); + CHECK(j2["msg"] == "hello"); + } + + const auto j3 = u8R"({"key": "value", "num": 42})"_json; + CHECK(j3["key"] == "value"); + CHECK(j3["num"] == 42); + } +#endif } // select the types to test - char8_t is only available since C++20 if and only diff --git a/tests/src/unit-json_pointer.cpp b/tests/src/unit-json_pointer.cpp index 9d6f1c326..a92a8df4d 100644 --- a/tests/src/unit-json_pointer.cpp +++ b/tests/src/unit-json_pointer.cpp @@ -788,4 +788,18 @@ TEST_CASE("JSON pointers") CHECK_FALSE(ptr_oj != ptr); } } + + // build with C++20 + // JSON_HAS_CPP_20 +#if defined(__cpp_char8_t) + SECTION("Using _json_pointer with char8_t literals #4945") + { + const json j = R"({"a": {"b": {"c": 123}}})"_json; + const auto p1 = "/a/b/c"_json_pointer; + CHECK(j[p1] == 123); + + const auto p2 = u8"/a/b/c"_json_pointer; + CHECK(j[p2] == 123); + } +#endif }