json_view: the library's std conversions read views directly (#5923)

* json_view: the library's std conversions read views directly

The library's from_json() overloads (containers, maps, std::array, C
arrays, pairs, tuples, optional, valarray, forward_list, enums, binary,
paths, and scalars) accept views: their traits use the view's
basic_json type, and the few accesses that differ (get_ptr) go through
small helpers. from_json() of a view now finds them; only the probe
still looks up by ADL only. get<T>() of a view thus converts these types
without materialize(), with the same values and exceptions; from an
object, a repeated key keeps the last value, as parse() does.

The view keeps its direct paths for vectors of the types it converts
directly (faster than from_json()) and for containers of views; its
other vector and map paths are replaced by from_json(). For basic_json,
std::valarray and std::forward_list are read in one pass (40 % and 3.5 %
fewer instructions); all other conversions are unchanged.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* json_view: enable_if_not_view_t instead of '!' in the from_json() templates

astyle spaces out the template argument list when it contains a negation;
the alias spells the condition with negation<> and leaves the lines alone.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* json_view: compact the template parameter lists astyle had spaced out

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann authored and GitHub committed 2026-10-26 20:13:31 +01:00
1 parent e5fe4ebdd2
commit 9e67bfa115
10 files changed
+618 -230

No files matched your search

+18 -13
View File
@@ -7822,14 +7822,16 @@ struct is_direct_value : std::integral_constant < bool,
template<typename Traits, typename Alloc, typename BasicJsonType, typename View>
struct is_direct_value<std::basic_string<char, Traits, Alloc>, BasicJsonType, View> : std::true_type {};
// (vectors of these, which are faster than through from_json(), and containers
// of views; other containers are read by the library's from_json())
template<typename U, typename A, typename BasicJsonType, typename View>
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : std::true_type {};
struct is_direct_value<std::vector<U, A>, BasicJsonType, View> : is_direct_value<U, BasicJsonType, View> {};
template<typename K, typename V, typename C, typename A, typename BasicJsonType, typename View>
struct is_direct_value<std::map<K, V, C, A>, BasicJsonType, View> : is_string_key<K> {};
template<typename K, typename C, typename A, typename BasicJsonType, typename View>
struct is_direct_value<std::map<K, View, C, A>, BasicJsonType, View> : is_string_key<K> {};
template<typename K, typename V, typename H, typename E, typename A, typename BasicJsonType, typename View>
struct is_direct_value<std::unordered_map<K, V, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
template<typename K, typename H, typename E, typename A, typename BasicJsonType, typename View>
struct is_direct_value<std::unordered_map<K, View, H, E, A>, BasicJsonType, View> : is_string_key<K> {};
} // namespace view
} // namespace detail
@@ -8671,22 +8673,25 @@ class basic_json_view
return *this;
}
template<typename U, typename A>
/// vectors of the types converted directly (faster than the library's
/// from_json()) and containers of views (no from_json() reads them: a view
/// is no value of BasicJsonType); other containers are read by from_json()
template<typename U, typename A, detail::enable_if_t<detail::view::is_direct_value<U, BasicJsonType, basic_json_view>::value, int> = 0>
std::vector<U, A> get_impl(detail::view::value_tag<std::vector<U, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
{
return detail::view::vector_value<basic_json_view, U, A>(*this);
}
template<typename K, typename V, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
std::map<K, V, C, A> get_impl(detail::view::value_tag<std::map<K, V, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
template<typename K, typename C, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
std::map<K, basic_json_view, C, A> get_impl(detail::view::value_tag<std::map<K, basic_json_view, C, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
{
return detail::view::map_value<std::map<K, V, C, A>>(*this);
return detail::view::map_value<std::map<K, basic_json_view, C, A>>(*this);
}
template<typename K, typename V, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
std::unordered_map<K, V, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, V, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
template<typename K, typename H, typename E, typename A, typename std::enable_if<detail::view::is_string_key<K>::value, int>::type = 0>
std::unordered_map<K, basic_json_view, H, E, A> get_impl(detail::view::value_tag<std::unordered_map<K, basic_json_view, H, E, A>> /*unused*/, detail::priority_tag<2> /*unused*/) const
{
return detail::view::map_value<std::unordered_map<K, V, H, E, A>>(*this);
return detail::view::map_value<std::unordered_map<K, basic_json_view, H, E, A>>(*this);
}
/// whether the from_json() of T's serializer reads views (see
@@ -8701,7 +8706,7 @@ class basic_json_view
? 2 : static_cast<int>(reads_view<T>::value) >;
/// types whose from_json() reads views, without materialize()
template < typename T, typename std::enable_if < reads_view<T>::value && std::is_default_constructible<T>::value, int >::type = 0 >
template<typename T, detail::enable_if_t<detail::conjunction<reads_view<T>, std::is_default_constructible<T>>::value, int> = 0>
T get_impl(detail::view::value_tag<T> /*unused*/, detail::priority_tag<1> /*unused*/) const
{
auto v = T();