1
0
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:
Niels Lohmann
2019-06-30 10:03:08 +02:00
parent 39011a1759
commit 258fa798f1
7 changed files with 338 additions and 23 deletions

View File

@ -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:
{