Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
192 views
in Technique[技术] by (71.8m points)

Adding XPointer/XPath searches to ALL(?) C++ JSON libraries, is it doable?

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...