mirror of
https://github.com/nlohmann/json.git
synced 2026-10-26 15:58:55 +00:00
json_view: from_json() of the macros reads views directly
get<T>() and get_to() of a view call T's from_json() with the view itself when that from_json() accepts views but not an unrelated probe type, and fall back to materialize() otherwise. The from_json() functions of the NLOHMANN_DEFINE_TYPE_*, NLOHMANN_DEFINE_DERIVED_TYPE_* and NLOHMANN_JSON_SERIALIZE_ENUM(_STRICT) macros accept basic_json values and views; a derived type whose base reads only json reads the base part through materialize(). The library's own from_json() overloads are not called with views: from_json() of a view (and of the probe) only looks up functions by ADL. New public trait nlohmann::is_json_view<T>, and the member type basic_json_type of basic_json_view. With duplicate keys, the members of such a T are those the view's lookups find (the first ones). bench_decode.cpp measures decoding into structs (4-6x faster than materialize().get<T>() on twitter, citm_catalog, and synthetic records). Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
23 files changed
+1342
-130
No files matched your search
@@ -106,6 +106,8 @@ class basic_json_view
|
||||
using navigation = detail::view::navigation<is_editable>;
|
||||
|
||||
public:
|
||||
/// the basic_json type of the document (it also marks views for is_json_view)
|
||||
using basic_json_type = BasicJsonType;
|
||||
using value_t = detail::value_t;
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
@@ -567,8 +569,10 @@ class basic_json_view
|
||||
|
||||
/// the value converted to T, as BasicJsonType::get<T>(): arithmetic types,
|
||||
/// strings (string_view_t without a copy), std::nullptr_t, std::vector,
|
||||
/// maps with string keys, and views are converted directly; other types
|
||||
/// through materialize().get<T>()
|
||||
/// maps with string keys, and views are converted directly; types whose
|
||||
/// from_json() accepts views (those of the NLOHMANN_DEFINE_TYPE_* and
|
||||
/// NLOHMANN_JSON_SERIALIZE_ENUM macros, say) read the view; other types
|
||||
/// go through materialize().get<T>()
|
||||
template<typename T>
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE T get() const
|
||||
{
|
||||
@@ -576,11 +580,12 @@ class basic_json_view
|
||||
}
|
||||
|
||||
/// as BasicJsonType::get_to(): the types get<T>() converts directly are
|
||||
/// assigned, all others are passed to from_json with v as it is
|
||||
/// assigned, all others are passed to from_json with v as it is (with
|
||||
/// the view if from_json() accepts views, else with materialize())
|
||||
template<typename T>
|
||||
T& get_to(T& v) const
|
||||
{
|
||||
get_to_impl(v, detail::view::is_direct_value<T, BasicJsonType, basic_json_view> {});
|
||||
get_to_impl(v, get_to_kind<T> {});
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -923,6 +928,26 @@ class basic_json_view
|
||||
return detail::view::map_value<std::unordered_map<K, V, H, E, A>>(*this);
|
||||
}
|
||||
|
||||
/// whether the from_json() of T's serializer reads views (see
|
||||
/// detail::has_view_from_json)
|
||||
template<typename T>
|
||||
using reads_view = detail::has_view_from_json<typename BasicJsonType::template json_serializer<T, void>, basic_json_view, T>;
|
||||
|
||||
/// how get_to() converts: 2 directly, 1 with a from_json() that reads
|
||||
/// views, 0 through materialize()
|
||||
template<typename T>
|
||||
using get_to_kind = std::integral_constant < int, detail::view::is_direct_value<T, BasicJsonType, basic_json_view>::value
|
||||
? 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 >
|
||||
T get_impl(detail::view::value_tag<T> /*unused*/, detail::priority_tag<1> /*unused*/) const
|
||||
{
|
||||
auto v = T();
|
||||
BasicJsonType::template json_serializer<T, void>::from_json(*this, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
/// everything else through the BasicJsonType value (from_json included)
|
||||
template<typename T>
|
||||
T get_impl(detail::view::value_tag<T> /*unused*/, detail::priority_tag<0> /*unused*/) const
|
||||
@@ -933,14 +958,20 @@ class basic_json_view
|
||||
// --- get_to() dispatch ---
|
||||
|
||||
template<typename T>
|
||||
void get_to_impl(T& v, std::true_type /*direct*/) const
|
||||
void get_to_impl(T& v, std::integral_constant<int, 2> /*direct*/) const
|
||||
{
|
||||
v = get<T>();
|
||||
}
|
||||
|
||||
/// from_json may keep parts of v (members a JSON object lacks, say)
|
||||
template<typename T>
|
||||
void get_to_impl(T& v, std::false_type /*direct*/) const
|
||||
void get_to_impl(T& v, std::integral_constant<int, 1> /*from_json reads views*/) const
|
||||
{
|
||||
BasicJsonType::template json_serializer<T, void>::from_json(*this, v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void get_to_impl(T& v, std::integral_constant<int, 0> /*through materialize()*/) const
|
||||
{
|
||||
materialize().get_to(v);
|
||||
}
|
||||
@@ -1645,6 +1676,15 @@ class basic_json_document
|
||||
std::unique_ptr<document_data, document_data::deleter> m_data{}; // NOLINT(readability-redundant-member-init)
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief whether T is a basic_json_view (of any BasicJsonType and view_mode)
|
||||
|
||||
For constraining templates that accept views, e.g. a from_json() written for
|
||||
both basic_json values and views.
|
||||
*/
|
||||
template<typename T>
|
||||
struct is_json_view : detail::is_json_view<T> {};
|
||||
|
||||
/// a parsed JSON text for json
|
||||
using json_document = basic_json_document<json>;
|
||||
/// a value of a json_document
|
||||
|
||||
Reference in new issue
Block a user