0

Is it possible to extend all(?) existing C++ JSON libraries with XPath/XPointer or subset with just one C++ implementation? At least those with iterators for object and array values?

I have reviewed three C++ JSON libraries (reviewing nlohmann, Boost.JSON and RapidJSON) to see the internals and check their search functionality. Some have implemented Json pointer. Json pointer is basic, almost like working with json as a name-value list.
XML has XPath and XPointer searches and rules are standardized. With XPath and XPointer you can do more.

One reason to reviewing these libraries was to see if it is possible to extend any of them with better search functionality. Or might it be possible to extend all(?) C++ JSON libraries at once?

A longer text describing this can be found here, trying to be brief.

I tried to do one traverse method that selects json values with one specific property name and that method should work an all tested JSON libraries. If I got that to work it may be possible to add more search logic and get it to work on almost all C++ JSON.

I got this C++ templated function to work an all tested json libraries. It can walk the JSON tree and select json values on all tested libraries.
What is needed to is to implement specializations of is_object, is_array, compare_name, get_value, begin and end. That are just one liners so it's easy.

template<typename json_value>
bool is_object( const json_value* p )
{ static_assert(sizeof(json_value) == 0, "Only specializations of is_object is allowed"); }

template<typename json_value>
bool is_array( const json_value* p )
{ static_assert(sizeof(json_value) == 0, "Only specializations of is_array is allowed"); }

template<typename iterator>
bool compare_name( iterator it, std::string_view stringName )
{ static_assert(sizeof(it) == 0, "Only specializations of compare_name is allowed"); }

template<typename iterator, typename json_value>
const json_value* get_value( iterator it )
{ static_assert(sizeof(it) == 0, "Only specializations of get_value is allowed"); }

template<typename iterator, typename json_value>
iterator begin( const json_value& v ) {  return std::begin( v ); }

template<typename iterator, typename json_value>
iterator end( const json_value& v ) {  return std::end( v ); }

// ------------------------------------------------
// Selects all json values that match property name
template<typename json_value, typename object_iterator,typename array_iterator = object_iterator>
uint32_t select( const json_value& jsonValue, std::string_view stringQuery, std::vector<const json_value*>* pvectorValue = nullptr )
{                                                                           assert( is_object( &jsonValue ) || is_array( &jsonValue ) );
   uint32_t uCount = 0;
   if( is_object( &jsonValue ) == true )  // found object ?
   {
      for( auto it = begin<object_iterator,json_value>( jsonValue ); it != end<object_iterator,json_value>( jsonValue ); it++ )
      {
         if( is_object( get_value<object_iterator,json_value>( it ) ) == true )
         {                                                                  // found object, scan it
            auto value = get_value<object_iterator,json_value>( it );
            uCount += select<json_value,object_iterator>( *value, stringQuery, pvectorValue );
         }
         else if( is_array( get_value<object_iterator,json_value>( it ) ) == true )
         {                                                                  // found array, scan it
            auto parray = get_value<object_iterator,json_value>( it );
            uCount += select<json_value,object_iterator,array_iterator>( *parray, stringQuery, pvectorValue ); 
         }
         else if( compare_name<object_iterator>( it, stringQuery ) == true )
         {                                                                  // property name matches, store value if pointer to vector
            if( pvectorValue != nullptr ) pvectorValue->push_back( get_value<object_iterator,json_value>( it ) );
            uCount++;
         }
      }
   }
   else if( is_array( &jsonValue ) == true )  // found array
   {
      for( auto it = begin<array_iterator,json_value>( jsonValue ); it != end<array_iterator,json_value>( jsonValue ); it++ )
      {
         if( is_object( get_value<array_iterator,json_value>( it ) ) == true )
         {                                                                  // found object, scan it
            auto value = get_value<array_iterator,json_value>( it );
            uCount += select<json_value,object_iterator>( *value, stringQuery, pvectorValue );
         }
         else if( is_array( get_value<array_iterator,json_value>( it ) ) == true )
         {                                                                  // found array, scan it
            auto parray = get_value<array_iterator,json_value>( it );
            uCount += select<json_value,object_iterator,array_iterator>( *parray, stringQuery, pvectorValue ); 
         }
      }
   }

   return uCount;
}

if this works and if I haven't forgot something, shouldn't it be possible to extend all libraries with just one implementation? The additional logic for XPath and XPointer is not dependent on the implementation of these C++ JSON libraries.

Am I missing something

Community
  • 1
  • 1
Per Ghosh
  • 449
  • 5
  • 10
  • 1
    No, it's not possible. I wrote one on my computer and I didn't give you the source code. So you can't add XPath support to it. – user253751 Dec 30 '20 at 18:48
  • The XPath logic I will of course write my self – Per Ghosh Dec 30 '20 at 18:51
  • 1
    The library I wrote on my computer doesn't use iterators, so your iterator code won't work. – user253751 Dec 30 '20 at 18:56
  • Ok, I misunderstood your first comment. Well I might be able to do it but then I have to implement iterators for your library. – Per Ghosh Dec 30 '20 at 19:00
  • 1
    Are you sure? My library only lets you access random keys, you can't ask for a specific one... and my library will continue getting more silly until you realize you can't write XPath for it :) – user253751 Dec 30 '20 at 19:06
  • Random access iterators works http://www.cplusplus.com/reference/iterator/RandomAccessIterator/ – Per Ghosh Dec 30 '20 at 19:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226628/discussion-between-per-ghosh-and-user253751). – Per Ghosh Dec 30 '20 at 21:01

0 Answers0