2026-02-13 19:15:05 +01:00
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
2026-04-17 21:00:35 +02:00
// | | |__ | | | | | | version 3.12.0
2026-02-13 19:15:05 +01:00
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
2026-04-17 21:00:35 +02:00
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
2026-02-13 19:15:05 +01:00
// SPDX-License-Identifier: MIT
# pragma once
# include <algorithm> // all_of
# include <cctype> // isdigit
# include <cerrno> // errno, ERANGE
# include <cstdlib> // strtoull
# ifndef JSON_NO_IO
# include <iosfwd> // ostream
# endif // JSON_NO_IO
# include <limits> // max
# include <numeric> // accumulate
# include <string> // string
# include <utility> // move
# include <vector> // vector
# include <nlohmann/detail/exceptions.hpp>
# include <nlohmann/detail/macro_scope.hpp>
# include <nlohmann/detail/string_concat.hpp>
# include <nlohmann/detail/string_escape.hpp>
# include <nlohmann/detail/value_t.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
template < typename RefStringType >
class json_pointer
{
// allow basic_json to access private members
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json ;
template < typename >
friend class json_pointer ;
template < typename T >
struct string_t_helper
{
using type = T ;
} ;
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct string_t_helper < NLOHMANN_BASIC_JSON_TPL >
{
using type = StringType ;
} ;
public :
// for backwards compatibility accept BasicJsonType
using string_t = typename string_t_helper < RefStringType > : : type ;
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
explicit json_pointer ( const string_t & s = " " )
: reference_tokens ( split ( s ) )
{ }
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
string_t to_string ( ) const
{
return std : : accumulate ( reference_tokens . begin ( ) , reference_tokens . end ( ) ,
string_t { } ,
[ ] ( const string_t & a , const string_t & b )
{
return detail : : concat ( a , ' / ' , detail : : escape ( b ) ) ;
} ) ;
}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .0 , to_string ( ) )
operator string_t ( ) const
{
return to_string ( ) ;
}
# ifndef JSON_NO_IO
/// @brief write string representation of the JSON pointer to stream
/// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
friend std : : ostream & operator < < ( std : : ostream & o , const json_pointer & ptr )
{
o < < ptr . to_string ( ) ;
return o ;
}
# endif
/// @brief append another JSON pointer at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
json_pointer & operator / = ( const json_pointer & ptr )
{
reference_tokens . insert ( reference_tokens . end ( ) ,
ptr . reference_tokens . begin ( ) ,
ptr . reference_tokens . end ( ) ) ;
return * this ;
}
/// @brief append an unescaped reference token at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
json_pointer & operator / = ( string_t token )
{
push_back ( std : : move ( token ) ) ;
return * this ;
}
/// @brief append an array index at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
json_pointer & operator / = ( std : : size_t array_idx )
{
return * this / = std : : to_string ( array_idx ) ;
}
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
friend json_pointer operator / ( const json_pointer & lhs ,
const json_pointer & rhs )
{
return json_pointer ( lhs ) / = rhs ;
}
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
friend json_pointer operator / ( const json_pointer & lhs , string_t token ) // NOLINT(performance-unnecessary-value-param)
{
return json_pointer ( lhs ) / = std : : move ( token ) ;
}
/// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
friend json_pointer operator / ( const json_pointer & lhs , std : : size_t array_idx )
{
return json_pointer ( lhs ) / = array_idx ;
}
/// @brief returns the parent of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
json_pointer parent_pointer ( ) const
{
if ( empty ( ) )
{
return * this ;
}
json_pointer res = * this ;
res . pop_back ( ) ;
return res ;
}
/// @brief remove last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
void pop_back ( )
{
if ( JSON_HEDLEY_UNLIKELY ( empty ( ) ) )
{
JSON_THROW ( detail : : out_of_range : : create ( 405 , " JSON pointer has no parent " , nullptr ) ) ;
}
reference_tokens . pop_back ( ) ;
}
/// @brief return last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/back/
const string_t & back ( ) const
{
if ( JSON_HEDLEY_UNLIKELY ( empty ( ) ) )
{
JSON_THROW ( detail : : out_of_range : : create ( 405 , " JSON pointer has no parent " , nullptr ) ) ;
}
return reference_tokens . back ( ) ;
}
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
void push_back ( const string_t & token )
{
reference_tokens . push_back ( token ) ;
}
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
void push_back ( string_t & & token )
{
reference_tokens . push_back ( std : : move ( token ) ) ;
}
/// @brief return whether pointer points to the root document
/// @sa https://json.nlohmann.me/api/json_pointer/empty/
bool empty ( ) const noexcept
{
return reference_tokens . empty ( ) ;
}
private :
/*!
@param[in] s reference token to be converted into an array index
@return integer representation of @a s
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index begins not with a digit
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.410 if an array index exceeds size_type
*/
template < typename BasicJsonType >
static typename BasicJsonType : : size_type array_index ( const string_t & s )
{
using size_type = typename BasicJsonType : : size_type ;
// error condition (cf. RFC 6901, Sect. 4)
if ( JSON_HEDLEY_UNLIKELY ( s . size ( ) > 1 & & s [ 0 ] = = ' 0 ' ) )
{
JSON_THROW ( detail : : parse_error : : create ( 106 , 0 , detail : : concat ( " array index ' " , s , " ' must not begin with '0' " ) , nullptr ) ) ;
}
// error condition (cf. RFC 6901, Sect. 4)
if ( JSON_HEDLEY_UNLIKELY ( s . size ( ) > 1 & & ! ( s [ 0 ] > = ' 1 ' & & s [ 0 ] < = ' 9 ' ) ) )
{
JSON_THROW ( detail : : parse_error : : create ( 109 , 0 , detail : : concat ( " array index ' " , s , " ' is not a number " ) , nullptr ) ) ;
}
const char * p = s . c_str ( ) ;
2026-04-17 21:00:35 +02:00
char * p_end = nullptr ; // NOLINT(misc-const-correctness)
2026-02-13 19:15:05 +01:00
errno = 0 ; // strtoull doesn't reset errno
const unsigned long long res = std : : strtoull ( p , & p_end , 10 ) ; // NOLINT(runtime/int)
if ( p = = p_end // invalid input or empty string
| | errno = = ERANGE // out of range
| | JSON_HEDLEY_UNLIKELY ( static_cast < std : : size_t > ( p_end - p ) ! = s . size ( ) ) ) // incomplete read
{
JSON_THROW ( detail : : out_of_range : : create ( 404 , detail : : concat ( " unresolved reference token ' " , s , " ' " ) , nullptr ) ) ;
}
// only triggered on special platforms (like 32bit), see also
// https://github.com/nlohmann/json/pull/2203
if ( res > = static_cast < unsigned long long > ( ( std : : numeric_limits < size_type > : : max ) ( ) ) ) // NOLINT(runtime/int)
{
JSON_THROW ( detail : : out_of_range : : create ( 410 , detail : : concat ( " array index " , s , " exceeds size_type " ) , nullptr ) ) ; // LCOV_EXCL_LINE
}
return static_cast < size_type > ( res ) ;
}
JSON_PRIVATE_UNLESS_TESTED :
json_pointer top ( ) const
{
if ( JSON_HEDLEY_UNLIKELY ( empty ( ) ) )
{
JSON_THROW ( detail : : out_of_range : : create ( 405 , " JSON pointer has no parent " , nullptr ) ) ;
}
json_pointer result = * this ;
result . reference_tokens = { reference_tokens [ 0 ] } ;
return result ;
}
private :
/*!
@brief create and return a reference to the pointed to value
@complexity Linear in the number of reference tokens.
@throw parse_error.109 if array index is not a number
@throw type_error.313 if value cannot be unflattened
*/
template < typename BasicJsonType >
BasicJsonType & get_and_create ( BasicJsonType & j ) const
{
auto * result = & j ;
// in case no reference tokens exist, return a reference to the JSON value
// j which will be overwritten by a primitive value
for ( const auto & reference_token : reference_tokens )
{
switch ( result - > type ( ) )
{
case detail : : value_t : : null :
{
if ( reference_token = = " 0 " )
{
// start a new array if reference token is 0
result = & result - > operator [ ] ( 0 ) ;
}
else
{
// start a new object otherwise
result = & result - > operator [ ] ( reference_token ) ;
}
break ;
}
case detail : : value_t : : object :
{
// create an entry in the object
result = & result - > operator [ ] ( reference_token ) ;
break ;
}
case detail : : value_t : : array :
{
// create an entry in the array
result = & result - > operator [ ] ( array_index < BasicJsonType > ( reference_token ) ) ;
break ;
}
/*
The following code is only reached if there exists a reference
token _and_ the current value is primitive. In this case, we have
an error situation, because primitive values may only occur as
single value; that is, with an empty list of reference tokens.
*/
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
JSON_THROW ( detail : : type_error : : create ( 313 , " invalid value to unflatten " , & j ) ) ;
}
}
return * result ;
}
/*!
@brief return a reference to the pointed to value
@note This version does not throw if a value is not present, but tries to
create nested values instead. For instance, calling this function
with pointer `"/this/that"` on a null value is equivalent to calling
`operator[]("this").operator[]("that")` on that value, effectively
changing the null value to an object.
@param[in] ptr a JSON value
@return reference to the JSON value pointed to by the JSON pointer
@complexity Linear in the length of the JSON pointer.
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template < typename BasicJsonType >
BasicJsonType & get_unchecked ( BasicJsonType * ptr ) const
{
for ( const auto & reference_token : reference_tokens )
{
// convert null values to arrays or objects before continuing
if ( ptr - > is_null ( ) )
{
// check if reference token is a number
const bool nums =
std : : all_of ( reference_token . begin ( ) , reference_token . end ( ) ,
[ ] ( const unsigned char x )
{
return std : : isdigit ( x ) ;
} ) ;
// change value to array for numbers or "-" or to object otherwise
* ptr = ( nums | | reference_token = = " - " )
? detail : : value_t : : array
: detail : : value_t : : object ;
}
switch ( ptr - > type ( ) )
{
case detail : : value_t : : object :
{
// use unchecked object access
ptr = & ptr - > operator [ ] ( reference_token ) ;
break ;
}
case detail : : value_t : : array :
{
if ( reference_token = = " - " )
{
// explicitly treat "-" as index beyond the end
ptr = & ptr - > operator [ ] ( ptr - > m_data . m_value . array - > size ( ) ) ;
}
else
{
// convert array index to number; unchecked access
ptr = & ptr - > operator [ ] ( array_index < BasicJsonType > ( reference_token ) ) ;
}
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
JSON_THROW ( detail : : out_of_range : : create ( 404 , detail : : concat ( " unresolved reference token ' " , reference_token , " ' " ) , ptr ) ) ;
}
}
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
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template < typename BasicJsonType >
BasicJsonType & get_checked ( BasicJsonType * ptr ) const
{
for ( const auto & reference_token : reference_tokens )
{
switch ( ptr - > type ( ) )
{
case detail : : value_t : : object :
{
// note: at performs range check
ptr = & ptr - > at ( reference_token ) ;
break ;
}
case detail : : value_t : : array :
{
if ( JSON_HEDLEY_UNLIKELY ( reference_token = = " - " ) )
{
// "-" always fails the range check
JSON_THROW ( detail : : out_of_range : : create ( 402 , detail : : concat (
" array index '-' ( " , std : : to_string ( ptr - > m_data . m_value . array - > size ( ) ) ,
" ) is out of range " ) , ptr ) ) ;
}
// note: at performs range check
ptr = & ptr - > at ( array_index < BasicJsonType > ( reference_token ) ) ;
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
JSON_THROW ( detail : : out_of_range : : create ( 404 , detail : : concat ( " unresolved reference token ' " , reference_token , " ' " ) , ptr ) ) ;
}
}
return * ptr ;
}
/*!
@brief return a const reference to the pointed to value
@param[in] ptr a JSON value
@return const reference to the JSON value pointed to by the JSON
pointer
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template < typename BasicJsonType >
const BasicJsonType & get_unchecked ( const BasicJsonType * ptr ) const
{
for ( const auto & reference_token : reference_tokens )
{
switch ( ptr - > type ( ) )
{
case detail : : value_t : : object :
{
// use unchecked object access
ptr = & ptr - > operator [ ] ( reference_token ) ;
break ;
}
case detail : : value_t : : array :
{
if ( JSON_HEDLEY_UNLIKELY ( reference_token = = " - " ) )
{
// "-" cannot be used for const access
JSON_THROW ( detail : : out_of_range : : create ( 402 , detail : : concat ( " array index '-' ( " , std : : to_string ( ptr - > m_data . m_value . array - > size ( ) ) , " ) is out of range " ) , ptr ) ) ;
}
// use unchecked array access
ptr = & ptr - > operator [ ] ( array_index < BasicJsonType > ( reference_token ) ) ;
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
JSON_THROW ( detail : : out_of_range : : create ( 404 , detail : : concat ( " unresolved reference token ' " , reference_token , " ' " ) , ptr ) ) ;
}
}
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
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
template < typename BasicJsonType >
const BasicJsonType & get_checked ( const BasicJsonType * ptr ) const
{
for ( const auto & reference_token : reference_tokens )
{
switch ( ptr - > type ( ) )
{
case detail : : value_t : : object :
{
// note: at performs range check
ptr = & ptr - > at ( reference_token ) ;
break ;
}
case detail : : value_t : : array :
{
if ( JSON_HEDLEY_UNLIKELY ( reference_token = = " - " ) )
{
// "-" always fails the range check
JSON_THROW ( detail : : out_of_range : : create ( 402 , detail : : concat (
" array index '-' ( " , std : : to_string ( ptr - > m_data . m_value . array - > size ( ) ) ,
" ) is out of range " ) , ptr ) ) ;
}
// note: at performs range check
ptr = & ptr - > at ( array_index < BasicJsonType > ( reference_token ) ) ;
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
JSON_THROW ( detail : : out_of_range : : create ( 404 , detail : : concat ( " unresolved reference token ' " , reference_token , " ' " ) , ptr ) ) ;
}
}
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
*/
template < typename BasicJsonType >
bool contains ( const BasicJsonType * ptr ) const
{
for ( const auto & reference_token : reference_tokens )
{
switch ( ptr - > type ( ) )
{
case detail : : value_t : : object :
{
if ( ! 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_HEDLEY_UNLIKELY ( reference_token = = " - " ) )
{
// "-" always fails the range check
return false ;
}
if ( JSON_HEDLEY_UNLIKELY ( reference_token . size ( ) = = 1 & & ! ( " 0 " < = reference_token & & reference_token < = " 9 " ) ) )
{
// invalid char
return false ;
}
if ( JSON_HEDLEY_UNLIKELY ( reference_token . size ( ) > 1 ) )
{
if ( JSON_HEDLEY_UNLIKELY ( ! ( ' 1 ' < = reference_token [ 0 ] & & reference_token [ 0 ] < = ' 9 ' ) ) )
{
// first char should be between '1' and '9'
return false ;
}
for ( std : : size_t i = 1 ; i < reference_token . size ( ) ; i + + )
{
if ( JSON_HEDLEY_UNLIKELY ( ! ( ' 0 ' < = reference_token [ i ] & & reference_token [ i ] < = ' 9 ' ) ) )
{
// other char should be between '0' and '9'
return false ;
}
}
}
const auto idx = array_index < BasicJsonType > ( reference_token ) ;
if ( idx > = ptr - > size ( ) )
{
// index out of range
return false ;
}
ptr = & ptr - > operator [ ] ( idx ) ;
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
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
@note This function is only called by the json_pointer constructor.
All exceptions below are documented there.
@throw parse_error.107 if the pointer is not empty or begins with '/'
@throw parse_error.108 if character '~' is not followed by '0' or '1'
*/
static std : : vector < string_t > split ( const string_t & reference_string )
{
std : : vector < string_t > result ;
// special case: empty reference string -> no reference tokens
if ( reference_string . empty ( ) )
{
return result ;
}
// check if nonempty reference string begins with slash
if ( JSON_HEDLEY_UNLIKELY ( reference_string [ 0 ] ! = ' / ' ) )
{
JSON_THROW ( detail : : parse_error : : create ( 107 , 1 , detail : : concat ( " JSON pointer must be empty or begin with '/' - was: ' " , reference_string , " ' " ) , nullptr ) ) ;
}
// extract the reference tokens:
// - slash: position of the last read slash (or end of string)
// - start: position after the previous slash
for (
// search for the first slash after the first character
std : : size_t slash = reference_string . find_first_of ( ' / ' , 1 ) ,
// set the beginning of the first reference token
start = 1 ;
// we can stop if start == 0 (if slash == string_t::npos)
start ! = 0 ;
// set the beginning of the next reference token
// (will eventually be 0 if slash == string_t::npos)
start = ( slash = = string_t : : npos ) ? 0 : slash + 1 ,
// find next slash
slash = reference_string . find_first_of ( ' / ' , start ) )
{
// use the text between the beginning of the reference token
// (start) and the last slash (slash).
auto reference_token = reference_string . substr ( start , slash - start ) ;
// check reference tokens are properly escaped
for ( std : : size_t pos = reference_token . find_first_of ( ' ~ ' ) ;
pos ! = string_t : : npos ;
pos = reference_token . find_first_of ( ' ~ ' , pos + 1 ) )
{
JSON_ASSERT ( reference_token [ pos ] = = ' ~ ' ) ;
// ~ must be followed by 0 or 1
if ( JSON_HEDLEY_UNLIKELY ( pos = = reference_token . size ( ) - 1 | |
( reference_token [ pos + 1 ] ! = ' 0 ' & &
reference_token [ pos + 1 ] ! = ' 1 ' ) ) )
{
JSON_THROW ( detail : : parse_error : : create ( 108 , 0 , " escape character '~' must be followed with '0' or '1' " , nullptr ) ) ;
}
}
// finally, store the reference token
detail : : unescape ( reference_token ) ;
result . push_back ( reference_token ) ;
}
return result ;
}
private :
/*!
@param[in] reference_string the reference string to the current value
@param[in] value the value to consider
@param[in,out] result the result object to insert values to
@note Empty objects or arrays are flattened to `null`.
*/
template < typename BasicJsonType >
static void flatten ( const string_t & reference_string ,
const BasicJsonType & value ,
BasicJsonType & result )
{
switch ( value . type ( ) )
{
case detail : : value_t : : array :
{
if ( value . m_data . m_value . array - > empty ( ) )
{
// flatten empty array as null
result [ reference_string ] = nullptr ;
}
else
{
// iterate array and use index as reference string
for ( std : : size_t i = 0 ; i < value . m_data . m_value . array - > size ( ) ; + + i )
{
2026-04-17 21:00:35 +02:00
flatten ( detail : : concat < string_t > ( reference_string , ' / ' , std : : to_string ( i ) ) ,
2026-02-13 19:15:05 +01:00
value . m_data . m_value . array - > operator [ ] ( i ) , result ) ;
}
}
break ;
}
case detail : : value_t : : object :
{
if ( value . m_data . m_value . object - > empty ( ) )
{
// flatten empty object as null
result [ reference_string ] = nullptr ;
}
else
{
// iterate object and use keys as reference string
for ( const auto & element : * value . m_data . m_value . object )
{
2026-04-17 21:00:35 +02:00
flatten ( detail : : concat < string_t > ( reference_string , ' / ' , detail : : escape ( element . first ) ) , element . second , result ) ;
2026-02-13 19:15:05 +01:00
}
}
break ;
}
case detail : : value_t : : null :
case detail : : value_t : : string :
case detail : : value_t : : boolean :
case detail : : value_t : : number_integer :
case detail : : value_t : : number_unsigned :
case detail : : value_t : : number_float :
case detail : : value_t : : binary :
case detail : : value_t : : discarded :
default :
{
// add primitive value with its reference string
result [ reference_string ] = value ;
break ;
}
}
}
/*!
@param[in] value flattened JSON
@return unflattened JSON
@throw parse_error.109 if array index is not a number
@throw type_error.314 if value is not an object
@throw type_error.315 if object values are not primitive
@throw type_error.313 if value cannot be unflattened
*/
template < typename BasicJsonType >
static BasicJsonType
unflatten ( const BasicJsonType & value )
{
if ( JSON_HEDLEY_UNLIKELY ( ! value . is_object ( ) ) )
{
JSON_THROW ( detail : : type_error : : create ( 314 , " only objects can be unflattened " , & value ) ) ;
}
BasicJsonType result ;
// iterate the JSON object values
for ( const auto & element : * value . m_data . m_value . object )
{
if ( JSON_HEDLEY_UNLIKELY ( ! element . second . is_primitive ( ) ) )
{
JSON_THROW ( detail : : type_error : : create ( 315 , " values in object must be primitive " , & element . second ) ) ;
}
// assign value to reference pointed to by JSON pointer; Note that if
// the JSON pointer is "" (i.e., points to the whole value), function
// get_and_create returns a reference to result itself. An assignment
// will then create a primitive value.
json_pointer ( element . first ) . get_and_create ( result ) = element . second ;
}
return result ;
}
// can't use conversion operator because of ambiguity
json_pointer < string_t > convert ( ) const &
{
json_pointer < string_t > result ;
result . reference_tokens = reference_tokens ;
return result ;
}
json_pointer < string_t > convert ( ) & &
{
json_pointer < string_t > result ;
result . reference_tokens = std : : move ( reference_tokens ) ;
return result ;
}
public :
# if JSON_HAS_THREE_WAY_COMPARISON
/// @brief compares two JSON pointers for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template < typename RefStringTypeRhs >
bool operator = = ( const json_pointer < RefStringTypeRhs > & rhs ) const noexcept
{
return reference_tokens = = rhs . reference_tokens ;
}
/// @brief compares JSON pointer and string for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .2 , operator = = ( json_pointer ) )
bool operator = = ( const string_t & rhs ) const
{
return * this = = json_pointer ( rhs ) ;
}
/// @brief 3-way compares two JSON pointers
template < typename RefStringTypeRhs >
std : : strong_ordering operator < = > ( const json_pointer < RefStringTypeRhs > & rhs ) const noexcept // *NOPAD*
{
return reference_tokens < = > rhs . reference_tokens ; // *NOPAD*
}
# else
/// @brief compares two JSON pointers for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator = = ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept ;
/// @brief compares JSON pointer and string for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template < typename RefStringTypeLhs , typename StringType >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator = = ( const json_pointer < RefStringTypeLhs > & lhs ,
const StringType & rhs ) ;
/// @brief compares string and JSON pointer for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template < typename RefStringTypeRhs , typename StringType >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator = = ( const StringType & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) ;
/// @brief compares two JSON pointers for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator ! = ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept ;
/// @brief compares JSON pointer and string for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template < typename RefStringTypeLhs , typename StringType >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator ! = ( const json_pointer < RefStringTypeLhs > & lhs ,
const StringType & rhs ) ;
/// @brief compares string and JSON pointer for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template < typename RefStringTypeRhs , typename StringType >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator ! = ( const StringType & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) ;
/// @brief compares two JSON pointer for less-than
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator < ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept ;
# endif
private :
/// the reference tokens
std : : vector < string_t > reference_tokens ;
} ;
# if !JSON_HAS_THREE_WAY_COMPARISON
// functions cannot be defined inside class due to ODR violations
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
inline bool operator = = ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept
{
return lhs . reference_tokens = = rhs . reference_tokens ;
}
template < typename RefStringTypeLhs ,
typename StringType = typename json_pointer < RefStringTypeLhs > : : string_t >
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .2 , operator = = ( json_pointer , json_pointer ) )
inline bool operator = = ( const json_pointer < RefStringTypeLhs > & lhs ,
const StringType & rhs )
{
return lhs = = json_pointer < RefStringTypeLhs > ( rhs ) ;
}
template < typename RefStringTypeRhs ,
typename StringType = typename json_pointer < RefStringTypeRhs > : : string_t >
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .2 , operator = = ( json_pointer , json_pointer ) )
inline bool operator = = ( const StringType & lhs ,
const json_pointer < RefStringTypeRhs > & rhs )
{
return json_pointer < RefStringTypeRhs > ( lhs ) = = rhs ;
}
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
inline bool operator ! = ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept
{
return ! ( lhs = = rhs ) ;
}
template < typename RefStringTypeLhs ,
typename StringType = typename json_pointer < RefStringTypeLhs > : : string_t >
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .2 , operator ! = ( json_pointer , json_pointer ) )
inline bool operator ! = ( const json_pointer < RefStringTypeLhs > & lhs ,
const StringType & rhs )
{
return ! ( lhs = = rhs ) ;
}
template < typename RefStringTypeRhs ,
typename StringType = typename json_pointer < RefStringTypeRhs > : : string_t >
JSON_HEDLEY_DEPRECATED_FOR ( 3.11 .2 , operator ! = ( json_pointer , json_pointer ) )
inline bool operator ! = ( const StringType & lhs ,
const json_pointer < RefStringTypeRhs > & rhs )
{
return ! ( lhs = = rhs ) ;
}
template < typename RefStringTypeLhs , typename RefStringTypeRhs >
inline bool operator < ( const json_pointer < RefStringTypeLhs > & lhs ,
const json_pointer < RefStringTypeRhs > & rhs ) noexcept
{
return lhs . reference_tokens < rhs . reference_tokens ;
}
# endif
NLOHMANN_JSON_NAMESPACE_END