Address the review of json_view element access

From gregmarr's review of #5622:

- count() counts every member with the key, so count(key) > 1 detects
  duplicate keys; it was contains() as 0/1 before.
- get_to() passes types that get<T>() does not convert directly to
  from_json with the existing value, as basic_json::get_to() does, so that
  a from_json which sets only the fields present keeps the others.
- array_index() checks the empty token and "-" first; the results are
  unchanged.
- Docs: no "if an exception is thrown" where a view never changes
  anything; the borrowed source must also stay unmodified; items() on a
  temporary view is safe; back()/front() notes shortened; the basic_json
  see-also entries say how the view's results can differ.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-18 10:05:51 +02:00
1 parent f2582daa62
commit 7b755737b4
27 files changed
+239 -114

No files matched your search

+24 -7
View File
@@ -251,7 +251,7 @@ class basic_json_view
{
if (is_discarded())
{
return basic_json_view();
return {};
}
detail::view::throw_type_error(305, "cannot use operator[] with a string argument with ", type_name());
}
@@ -277,7 +277,7 @@ class basic_json_view
{
if (is_discarded())
{
return basic_json_view();
return {};
}
detail::view::throw_type_error(305, "cannot use operator[] with a numeric argument with ", type_name());
}
@@ -300,7 +300,7 @@ class basic_json_view
{
if (NLOHMANN_VIEW_UNLIKELY(is_discarded()))
{
return basic_json_view();
return {};
}
return detail::view::resolve_pointer(*this, detail::json_pointer_access::reference_tokens(ptr), detail::view::pointer_mode::unchecked);
}
@@ -473,11 +473,11 @@ class basic_json_view
return !detail::view::resolve_pointer(*this, detail::json_pointer_access::reference_tokens(ptr), detail::view::pointer_mode::contains).is_discarded();
}
/// 1 if this is an object with a member with this key, else 0 (duplicate
/// keys count once)
/// the number of members with this key (more than 1 if the key occurs
/// more than once); 0 if this is not an object
size_type count(string_view_t key) const
{
return contains(key) ? 1 : 0;
return is_object() ? detail::view::count_members(*m_doc, m_node, key.data(), key.size()) : 0;
}
size_type count(const char* key) const
@@ -544,10 +544,12 @@ class basic_json_view
return get_impl(detail::view::value_tag<T> {}, detail::priority_tag<2> {});
}
/// as BasicJsonType::get_to(): the types get<T>() converts directly are
/// assigned, all others are passed to from_json with v as it is
template<typename T>
T& get_to(T& v) const
{
v = get<T>();
get_to_impl(v, detail::view::is_direct_value<T, BasicJsonType, basic_json_view> {});
return v;
}
@@ -691,6 +693,21 @@ class basic_json_view
return materialize().template get<T>();
}
// --- get_to() dispatch ---
template<typename T>
void get_to_impl(T& v, std::true_type /*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
{
materialize().get_to(v);
}
const document_data* m_doc = nullptr;
const node* m_node = nullptr;
};