Writing generic code¶
View types¶
A view's type names its BasicJsonType and its view_mode: json_view is basic_json_view<json, view_mode::read_only>, and json_editable_view is basic_json_view<json, view_mode::editable>. These are different types. The only conversion between them turns a view of a read-only document into a view of an editable document of the same BasicJsonType, so a function written for one shortcut accepts few other views:
void print_names(json_view v); // accepts neither an ordered_json_view nor a json_editable_view
void print_names(json_editable_view v); // also accepts a json_view, but no ordered_json_view
This is the same pitfall as a to_json/from_json written for json instead of any BasicJsonType, which then does not work for ordered_json. The shortcuts are for declaring documents and views; a function that takes a view names the views it accepts with a template:
// views of editable documents only
template<typename BasicJsonType>
void f(basic_json_view<BasicJsonType, view_mode::editable> v);
// views of read-only documents only
template<typename BasicJsonType>
void f(basic_json_view<BasicJsonType, view_mode::read_only> v);
// views of either document type
template<typename BasicJsonType, view_mode Mode>
void f(basic_json_view<BasicJsonType, Mode> v);
Views are passed by value: they are two pointers, cheap to copy, like a std::string_view. A const& works as well, but a non-const reference does not bind to the views that root(), operator[], and at() return, so f(doc.root()) would not compile.
There is no conversion from an editable view to a read-only one, by design: the mode decides how a view walks the index. A read-only view reads a container in place, while a view of an editable document follows the links that edits leave behind, so a read-only view of an edited document would read stale values. The other direction is safe: a read-only document has no edits, so a view of it converts to an editable view, which reads it like an editable document before its first edit. A template deduces the mode without conversions, so the template forms above still accept only the modes they name. Views of both modes compare with operator==.
is_json_view<T> tells views from other types, for constraints that cannot be written as a basic_json_view<...> parameter.
A from_json() that reads views¶
get<T>() on a view calls T's from_json() with the view itself if that from_json() accepts views, and with materialize() otherwise. The from_json() functions of the NLOHMANN_DEFINE_TYPE_*, NLOHMANN_DEFINE_DERIVED_TYPE_*, and NLOHMANN_JSON_SERIALIZE_ENUM macros, and those of the library for the standard types, accept views, so these types need nothing else. For decoding the statuses of twitter.json into structs, reading the view is about 5 times faster than materialize().get<T>().
A hand-written from_json() reads views if it is constrained to json values and views:
template < typename J, typename std::enable_if <
nlohmann::is_json_view<J>::value || std::is_same<J, nlohmann::json>::value, int >::type = 0 >
void from_json(const J& j, person& p)
{
p.name = j.at("name").template get<std::string>();
p.age = j.at("age").template get<int>();
}
Its body may only use what views and basic_json have in common: the type checks, at(), operator[], contains(), value(), size(), iteration and items(), and get<T>()/get_to(). An unconstrained template<typename BasicJsonType> void from_json(const BasicJsonType& j, person& p), as in arbitrary type conversions, is never called with a view, as it might use basic_json functions a view does not have; such a type is converted through materialize(). A from_json() for json only is converted through materialize() as well.
Reading the view and materialize().get<T>() give the same result, except for an object with a repeated key; see Duplicate keys.
to_json() is unaffected: it writes basic_json values, never views.
See also¶
- Zero-copy JSON views - overview
is_json_view- type trait to detect viewsview_mode- read-only and editable views- Reading values - what
get<T>()converts without materializing
Version history¶
- Added in version 3.13.0 unreleased.