Skip to content

Commit

Permalink
Make std::filesystem::path conversion to/from UTF-8 encoded string ex…
Browse files Browse the repository at this point in the history
…plicit.
  • Loading branch information
Richard Musil committed Jan 26, 2025
1 parent d0789e3 commit 61a26dd
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
7 changes: 6 additions & 1 deletion include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,12 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
{
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
#ifdef JSON_HAS_CPP_20
p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
#else
p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
#endif
}
#endif

Expand Down
7 changes: 6 additions & 1 deletion include/nlohmann/detail/conversions/to_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,12 @@ inline void to_json(BasicJsonType& j, const T& t)
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std_fs::path& p)
{
j = p.string();
#ifdef JSON_HAS_CPP_20
const std::u8string s = p.u8string();
j = std::string(s.begin(), s.end());
#else
j = p.u8string(); // returns std::string in C++17
#endif
}
#endif

Expand Down
14 changes: 12 additions & 2 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5319,7 +5319,12 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
{
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
#ifdef JSON_HAS_CPP_20
p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
#else
p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
#endif
}
#endif

Expand Down Expand Up @@ -6080,7 +6085,12 @@ inline void to_json(BasicJsonType& j, const T& t)
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const std_fs::path& p)
{
j = p.string();
#ifdef JSON_HAS_CPP_20
const std::u8string s = p.u8string();
j = std::string(s.begin(), s.end());
#else
j = p.u8string(); // returns std::string in C++17
#endif
}
#endif

Expand Down
24 changes: 24 additions & 0 deletions tests/src/unit-conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,29 @@ TEST_CASE("JSON to enum mapping")
}

#ifdef JSON_HAS_CPP_17
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
TEST_CASE("std::filesystem::path")
{
SECTION("ascii")
{
json j_string = "Path";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json j_path = p;

CHECK(j_path.template get<std::string>() == j_string.template get<std::string>());
}

SECTION("utf-8")
{
json j_string = "P\xc4\x9b\xc5\xa1ina";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json j_path = p;

CHECK(j_path.template get<std::string>() == j_string.template get<std::string>());
}
}
#endif

#ifndef JSON_USE_IMPLICIT_CONVERSIONS
TEST_CASE("std::optional")
{
Expand Down Expand Up @@ -1714,6 +1737,7 @@ TEST_CASE("std::optional")
CHECK(json(opt_object) == j_object);
CHECK(std::map<std::string, std::optional<int>>(j_object) == opt_object);
}

}
#endif
#endif
Expand Down

0 comments on commit 61a26dd

Please sign in to comment.