Skip to content

Commit 7b72cc3

Browse files
author
khloodelhossiny
committed
support types convertible to string_view as JSON keys
Signed-off-by: khloodelhossiny <khlood.elhossiny.gmail.com>
1 parent 3ed64e5 commit 7b72cc3

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

include/nlohmann/detail/meta/type_traits.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -621,11 +621,14 @@ using is_usable_as_key_type = typename std::conditional <
621621
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
622622
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
623623
using is_usable_as_basic_json_key_type = typename std::conditional <
624-
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
625-
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
626-
RequireTransparentComparator, ExcludeObjectKeyType>::value
627-
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
628-
std::true_type,
624+
(is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
625+
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
626+
RequireTransparentComparator, ExcludeObjectKeyType>::value
627+
&& !is_json_iterator_of<BasicJsonType, KeyType>::value)
628+
#ifdef JSON_HAS_CPP_17
629+
|| std::is_convertible<KeyType, std::string_view>::value
630+
#endif
631+
, std::true_type,
629632
std::false_type >::type;
630633

631634
template<typename ObjectType, typename KeyType>

single_include/nlohmann/json.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4164,11 +4164,14 @@ using is_usable_as_key_type = typename std::conditional <
41644164
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
41654165
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
41664166
using is_usable_as_basic_json_key_type = typename std::conditional <
4167-
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4168-
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4169-
RequireTransparentComparator, ExcludeObjectKeyType>::value
4170-
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
4171-
std::true_type,
4167+
(is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4168+
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4169+
RequireTransparentComparator, ExcludeObjectKeyType>::value
4170+
&& !is_json_iterator_of<BasicJsonType, KeyType>::value)
4171+
#ifdef JSON_HAS_CPP_17
4172+
|| std::is_convertible<KeyType, std::string_view>::value
4173+
#endif
4174+
, std::true_type,
41724175
std::false_type >::type;
41734176

41744177
template<typename ObjectType, typename KeyType>

tests/src/unit-element_access2.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,3 +1790,55 @@ TEST_CASE_TEMPLATE("element access 2 (additional value() tests)", Json, nlohmann
17901790
#endif
17911791
}
17921792
}
1793+
1794+
#ifdef JSON_HAS_CPP_17
1795+
TEST_CASE("operator[] with user-defined std::string_view-convertible types")
1796+
{
1797+
using json = nlohmann::json;
1798+
1799+
class TestClass
1800+
{
1801+
std::string key_data_ = "foo";
1802+
1803+
public:
1804+
operator std::string_view() const
1805+
{
1806+
return key_data_;
1807+
}
1808+
};
1809+
1810+
struct TestStruct
1811+
{
1812+
operator std::string_view() const
1813+
{
1814+
return "bar";
1815+
}
1816+
};
1817+
1818+
json j = {{"foo", "from_class"}, {"bar", "from_struct"}};
1819+
TestClass foo_obj;
1820+
TestStruct bar_obj;
1821+
1822+
SECTION("read access")
1823+
{
1824+
CHECK(j[foo_obj] == "from_class");
1825+
CHECK(j[TestClass{}] == "from_class");
1826+
CHECK(j[bar_obj] == "from_struct");
1827+
CHECK(j[TestStruct{}] == "from_struct");
1828+
}
1829+
1830+
SECTION("write access")
1831+
{
1832+
j[TestClass{}] = "updated_class";
1833+
j[TestStruct{}] = "updated_struct";
1834+
CHECK(j["foo"] == "updated_class");
1835+
CHECK(j["bar"] == "updated_struct");
1836+
1837+
SECTION("direct std::string_view access")
1838+
{
1839+
CHECK(j[std::string_view{"foo"}] == "updated_class");
1840+
CHECK(j[std::string_view{"bar"}] == "updated_struct");
1841+
}
1842+
}
1843+
}
1844+
#endif

0 commit comments

Comments
 (0)