mirror of
https://github.com/nlohmann/json.git
synced 2025-07-29 23:01:16 +03:00
✨ add contains function for JSON pointers
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm> // all_of
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
@ -369,7 +370,7 @@ class json_pointer
|
||||
// j which will be overwritten by a primitive value
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (result->m_type)
|
||||
switch (result->type())
|
||||
{
|
||||
case detail::value_t::null:
|
||||
{
|
||||
@ -446,14 +447,14 @@ class json_pointer
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
// convert null values to arrays or objects before continuing
|
||||
if (ptr->m_type == detail::value_t::null)
|
||||
if (ptr->is_null())
|
||||
{
|
||||
// check if reference token is a number
|
||||
const bool nums =
|
||||
std::all_of(reference_token.begin(), reference_token.end(),
|
||||
[](const char x)
|
||||
[](const unsigned char x)
|
||||
{
|
||||
return x >= '0' and x <= '9';
|
||||
return std::isdigit(x);
|
||||
});
|
||||
|
||||
// change value to array for numbers or "-" or to object otherwise
|
||||
@ -462,7 +463,7 @@ class json_pointer
|
||||
: detail::value_t::object;
|
||||
}
|
||||
|
||||
switch (ptr->m_type)
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
@ -521,7 +522,7 @@ class json_pointer
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->m_type)
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
@ -586,7 +587,7 @@ class json_pointer
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->m_type)
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
@ -645,7 +646,7 @@ class json_pointer
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->m_type)
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
@ -692,6 +693,77 @@ class json_pointer
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if an array index was not a number
|
||||
*/
|
||||
bool contains(const BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (not ptr->contains(reference_token))
|
||||
{
|
||||
// we did not find the key in the object
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr = &ptr->operator[](reference_token);
|
||||
break;
|
||||
}
|
||||
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (JSON_UNLIKELY(reference_token == "-"))
|
||||
{
|
||||
// "-" always fails the range check
|
||||
return false;
|
||||
}
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(106, 0,
|
||||
"array index '" + reference_token +
|
||||
"' must not begin with '0'"));
|
||||
}
|
||||
|
||||
JSON_TRY
|
||||
{
|
||||
const auto idx = static_cast<size_type>(array_index(reference_token));
|
||||
if (idx >= ptr->size())
|
||||
{
|
||||
// index out of range
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr = &ptr->operator[](idx);
|
||||
break;
|
||||
}
|
||||
JSON_CATCH(std::invalid_argument&)
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// we do not expect primitive values if there is still a
|
||||
// reference token to process
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no reference token left means we found a primitive value
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief split the string input to reference tokens
|
||||
|
||||
@ -813,7 +885,7 @@ class json_pointer
|
||||
const BasicJsonType& value,
|
||||
BasicJsonType& result)
|
||||
{
|
||||
switch (value.m_type)
|
||||
switch (value.type())
|
||||
{
|
||||
case detail::value_t::array:
|
||||
{
|
||||
|
Reference in New Issue
Block a user