首页 > 解决方案 > 将 XPointer/XPath 搜索添加到所有(?) C++ JSON 库,是否可行?

问题描述

是否可以使用 XPath/XPointer 或仅使用一个 C++ 实现的子集来扩展所有(?)现有 C++ JSON 库?至少那些具有对象和数组值的迭代器?

我查看了三个 C++ JSON 库(查看 nlohmann、Boost.JSON 和 RapidJSON)来查看内部结构并检查它们的搜索功能。有些已经实现了Json 指针。Json 指针是基本的,几乎就像使用 json 作为名称-值列表一样。
XML 具有 XPath 和 XPointer 搜索,并且规则是标准化的。使用 XPath 和 XPointer,您可以做更多事情。

审查这些库的一个原因是看看是否可以用更好的搜索功能扩展它们。或者是否可以一次扩展所有(?)C++ JSON 库?

可以在此处找到描述此内容的较长文本,尽量简短。

我尝试使用一种遍历方法来选择具有一个特定属性名称的 json 值,并且该方法应该适用于所有经过测试的 JSON 库。如果我让它工作,可能会添加更多搜索逻辑并让它在几乎所有 C++ JSON 上工作。

我得到了这个 C++ 模板函数来处理所有经过测试的 json 库。它可以遍历 JSON 树并在所有测试的库上选择 json 值。
需要的是实现is_objectis_arraycompare_nameget_valuebegin的专业化end。那只是一个衬垫,所以很容易。

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;
}

如果这可行并且如果我没有忘记某些东西,难道不应该只用一个实现来扩展所有库吗?XPath 和 XPointer 的附加逻辑不依赖于这些 C++ JSON 库的实现。

我错过了什么吗

标签: c++jsonxmlrapidjsonnlohmann-json

解决方案


推荐阅读