【问题标题】:Boost Fusion and Boost property_tree for de serialization of a structureBoost Fusion 和 Boost property_tree 用于结构的反序列化
【发布时间】:2014-06-11 04:45:36
【问题描述】:

我正在尝试使用 boost::property_tree 反序列化 JSON 数据。我已经建立了一个 boost fusion 序列来识别结构成员元素的类型,并使用一个函数来反序列化一个适当的 JSON 树。它曾经适用于包含普通数据类型的结构。当我尝试对包含结构的结构应用相同的操作时,逻辑失败并导致编译器错误。谁能看到我哪里出错了。

#include <boost/fusion/include/sequence.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <boost/fusion/include/is_sequence.hpp>

#include <boost/mpl/eval_if.hpp>
#include <boost/type_traits.hpp> 

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/lexical_cast.hpp>

#include <boost/foreach.hpp>

#include <type_traits>
#include <typeinfo>
#include <vector>
#include <list>

std::string type_name_to_recover = "";

template<typename type_t> 
struct is_container : public std::false_type {};

template<typename type_t, typename allocator_t> 
struct is_container < std::vector < type_t , allocator_t> > : public std::true_type {};

template<typename type_t, typename allocator_t> 
struct is_container < std::list < type_t , allocator_t> >  : public std::true_type {};

template <typename type_t> 
struct simple_serializer;


template <typename sequence_t, typename index_t> 
struct sequence_iterator
{
typedef typename boost::fusion::result_of::value_at<sequence_t, index_t>::type current_type_t;
typedef typename boost::mpl::next<index_t>::type next_index_t;
typedef boost::fusion::extension::struct_member_name<sequence_t, index_t::value> type_name_t;

static inline void read_json( boost::property_tree::ptree  &pt, sequence_t& sequence) 
{
    type_name_to_recover = type_name_t::call();
    simple_serializer<current_type_t>::read_json(pt, boost::fusion::at<index_t>(sequence));
    type_name_to_recover = "";
    sequence_iterator<sequence_t, next_index_t>::read_json(pt, sequence);
}

};


//tail of the sequence
template <typename sequence_t>
struct sequence_iterator<sequence_t, typename         boost::fusion::result_of::size<sequence_t>::type > 
{
static inline void read_json( boost::property_tree::ptree  &pt, sequence_t& sequence) { }
};

template < typename sequence_t >
struct sequence_iterator_final : sequence_iterator < sequence_t, boost::mpl::int_< 0 > > {};



////////////////////////////////////////////////////////
//Plain old types serializer
////////////////////////////////////////////////////////
template <typename type_t> 
struct serialize_pod
{
typedef serialize_pod<type_t> type;

static inline void read_json( boost::property_tree::ptree  &pt, type_t& t) 
{
    auto v = pt.get_child(type_name_to_recover);
    t =  boost::lexical_cast<type_t>(v.data());
}
};

////////////////////////////////////////////////////////
//Sequence serializer
////////////////////////////////////////////////////////

template <typename sequence_t> 
struct serialize_sequence 
{
typedef serialize_sequence<sequence_t> type;

static inline void read_json( boost::property_tree::ptree  &pt, sequence_t& sequence) 
{
    sequence_iterator_final<sequence_t>::read_json(pt, sequence);
}

};

////////////////////////////////////////////////////////
//Container serializer
////////////////////////////////////////////////////////
template <typename container_type_t> 
struct serialize_container 
{
typedef serialize_container<container_type_t> type;

template <typename type_t>
static void read_json( boost::property_tree::ptree  &pt, std::vector<type_t> &t) 
{
    std::string temp_name = type_name_to_recover;
    type_name_to_recover = "";
    BOOST_FOREACH( boost::property_tree::ptree::value_type &tree_node_value, pt.get_child(temp_name) )
    {
        boost::property_tree::ptree subtree = (boost::property_tree::ptree) tree_node_value.second ;
        if( subtree.empty() )
        {
            auto tree_node_y = subtree.data();
            type_t type_val;
            simple_serializer<type_t>::read_json(tree_node_y, type_val);
            t.push_back(type_val);
        }
        else
        {
            auto tree_node_x = subtree.data();
            type_t type_val;
            simple_serializer<type_t>::read_json(tree_node_x, type_val);
            t.push_back(type_val);
        }
    }
}

};


template <typename type_t> 
struct resolve_serializer_type 
{
  typedef 
typename boost::mpl::eval_if< boost::fusion::traits::is_sequence < type_t > , serialize_sequence < type_t > , 
typename boost::mpl::eval_if< is_container < type_t > , boost::mpl::identity < serialize_container < type_t > >,
serialize_pod < type_t >  >  > 
  ::type type;
};

//
template <typename type_t> 
struct simple_serializer : public resolve_serializer_type<type_t>::type { };




struct StructB
{
int s;
std::vector<int> vi_b; 
};

struct StructA
{ 
int v;  
std::vector<int> vi; 
std::vector<StructB> lb;
};

BOOST_FUSION_ADAPT_STRUCT( StructB, (int , s) (std::vector<int>, vi_b) )
BOOST_FUSION_ADAPT_STRUCT( StructA, (int, v) (std::vector<int>, vi) (std::vector<StructB>, lb ) )


int main(int argc, char *argv[]) 
{

StructA sa_in;

std::string json_data = "{\"v\":20,\"vi\":[123,456,123],\"lb\":[{\"s\":999,\"vi_b\":[909,808]},{\"s\":888,\"vi_b\":[707]},{\"s\":777,\"vi_b\":[606,505,404,303]}]}";

std::stringstream is(json_data);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(is, pt);

simple_serializer<StructA>::read_json( pt , sa_in);
}

错误信息: 1>e:\fusiongarage\apr_25\source.cpp(122): 错误 C2664: 'serialize_sequence::read_json' : 无法将参数 1 从 'std::basic_string<_elem>' 转换为 'boost::property_tree ::ptree &' 1> 与 1> [ 1> 序列_t=结构B 1>] 1> 和 1> [ 1> _Elem=字符, 1> _Traits=std::char_traits, 1> _Ax=std::分配器 1>] 1> e:\fusiongarage\apr_25\source.cpp(46) : 请参阅正在编译的函数模板实例化 'void serialize_container::read_json(boost::property_tree::ptree &,std::vector<_ty> &)' 的参考 1> 与 1> [ 1> container_type_t=std::vector, 1> _Ty=结构B 1>] 1> e:\fusiongarage\apr_25\source.cpp(44) : 编译类模板成员函数'void sequence_iterator::read_json(boost::property_tree::ptree &,sequence_t &)' 1> 与 1> [ 1> 序列_t=结构A, 1> index_t=boost::mpl::int_ 1>] 1> e:\fusiongarage\apr_25\source.cpp(48) : 参见正在编译的类模板实例化 'sequence_iterator' 的引用 1> 与 1> [ 1> 序列_t=结构A, 1> index_t=boost::mpl::int_ 1>] 1> 1>构建失败。

【问题讨论】:

    标签: c++ json serialization


    【解决方案1】:

    看来 read_json 函数需要为包含其他结构的结构传递一个子树。如下更改容器序列化程序似乎可以解决问题。任何人都可以确认该解决方案是有效的。

    ////////////////////////////////////////////////////////
    //Container serializer
    ////////////////////////////////////////////////////////
    template <typename container_type_t> 
    struct serialize_container 
    {
    typedef serialize_container<container_type_t> type;
    
    template <typename type_t>
    static void read_json( boost::property_tree::ptree  &pt, std::vector<type_t> &t) 
    {
        std::string temp_name = type_name_to_recover;
        type_name_to_recover = "";
        BOOST_FOREACH( boost::property_tree::ptree::value_type &tree_node_value, pt.get_child(temp_name) )
        {
            boost::property_tree::ptree subtree = (boost::property_tree::ptree) tree_node_value.second ;
            if( subtree.empty() )
            {
                type_t type_val;
                simple_serializer<type_t>::read_json(subtree, type_val);
                t.push_back(type_val);
            }
            else
            {
                type_t type_val;
    
                std::stringstream os;
                boost::property_tree::write_json(os, subtree);
    
                boost::property_tree::ptree pt_x;
                boost::property_tree::json_parser::read_json(os, pt_x);
    
                simple_serializer<type_t>::read_json(pt_x, type_val);
    
                t.push_back(type_val);
            }
        }
    }
    
    };
    

    【讨论】:

      猜你喜欢
      • 2015-03-19
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 1970-01-01
      • 2012-09-05
      • 1970-01-01
      • 2020-08-26
      • 2020-05-30
      相关资源
      最近更新 更多