Boost解析Json字符串
博客专区 > IcedBeer 的博客 > 博客详情
Boost解析Json字符串
IcedBeer 发表于1年前
Boost解析Json字符串
  • 发表于 1年前
  • 阅读 152
  • 收藏 1
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

最近项目中,几年前的配置突然改动了很多, 为了迎合新的修改,故将配置格式由ini升级成了json格式;

所用到的配置文件格式相比较网上的大部分文章稍微复杂点,下面列出一小段,供大家参考。

JSON文件配置格式如下:

    "100012": [
{"名字":"玫瑰"},
{"道具类型":"普通"},
{"经验值":20},
{"主播获得积分":20},
{"玩家获得积分":20},
{"返现银子":0},
{"价格":2},
{"货币类型":"元宝"},
{"说明":"送你一朵玫瑰花!"},
{"特效说明":"一次性赠送10个触发特效和1次弹幕"},
{"弹幕次数":[{"1":0},{"10":1},{"99":2},{"520":3},{"1314":4}]},
{"动画次数":[{"1":0},{"10":1},{"99":1},{"520":1},{"1314":1}]}
        ],
    "100013": [
{"名字":"吻"},
{"道具类型":"浪漫"},
{"经验值":50},
{"主播获得积分":50},
{"玩家获得积分":50},
{"返现银子":2500},
{"价格":5},
{"货币类型":"元宝"},
{"说明":"幸运的祝福!"},
{"特效说明":"一次性赠送10个触发特效和2次弹幕"},
{"弹幕次数":[{"1":1},{"10":2},{"99":3},{"520":4},{"1314":5}]},
{"动画次数":[{"1":0},{"10":1},{"99":1},{"520":1},{"1314":1}]}
        ]
}

读取JSON配置,首先定义结构器,包含了配置中所以的字段:

typedef struct _CHARMPROP
{
    long    lPropID;
    string  strPropName;
    string  strText;                //说明
    string  strType;                //类型
    float   fPrice;                 //价格
    string  strMoneyType;           //货币类型
    long    lDesGetCharm;           //接受者增加的魅力值
    long    recver_score;           //接受者获得的积分
    long    sender_score;           //发送者获得的积分
    int     return_sliver;          //返还银子数量
    string  texiao_str;             //特效说明
    map<long, int>   donghua_num;   //动画次数
    map<long, int>   danmu_num;     //弹幕次数
    ~_CHARMPROP()
    {
        donghua_num.clear();
        danmu_num.clear();
    }
}CHARMPROP, *PCharmProp;

在解析过程中,除了使用了c++标准库之外,还有boost的一些库,Windows下只需要包含如些通文件即可:

#include "boost/shared_ptr.hpp"                  //智能指针
#include "boost/lexical_cast.hpp"                //字符串、数据转换
#include "boost/property_tree/ptree.hpp"         //JSon解析
#include "boost/property_tree/json_parser.hpp"   //JSon解析
#include "boost/foreach.hpp"

在类中添加成员变量,用于保存读出的配置参数:

map<long, boost::shared_ptr<CHARMPROP> >_charm_map; 

解析函数:由于公司配置文件都是加密的,所以通过解密工具读取文件,可以返回配置中的所有字符串,boost json可以通过字符串流解析,或者直接传递文件名进行解析,由boost json自行读取json文本;

BOOL CGlobalConfig::LoadCharmConfigUct()
{
    _charm_map.clear();
    try
    {
        LPCSTR data_str = NULL;
        //... 
        //此处略去几行,就是给data_str赋json字符串
        if (NULL == data_str)
        {
            //读取文件失败
            return FALSE;
        }
        //格式化到字符串流中
        stringstream str_stream;
        str_stream << data_str;
        boost::property_tree::ptree     ptree_root, pt_tmp, pt_tmp2;
        //未加密文件可以将str_stream替换为你的文件名
        //解析json格式,并将所有节点信息保存到ptree_root结构中
        boost::property_tree::json_parser::read_json<boost::property_tree::ptree>(str_stream, ptree_root);
        
        long charm_id(0); //道具唯一标识ID
        //从ptree_root枚举所有的变量列表,如"100012","100013"
        BOOST_FOREACH(boost::property_tree::ptree::value_type& v, ptree_root)
        {
            //获取key并转换成long型
            charm_id = boost::lexical_cast<long>(v.first);
            //新建一个内存堆,存放后面读取到的数据
            boost::shared_ptr<CHARMPROP> pCharm(new CHARMPROP);
            pCharm->lPropID = charm_id;
            //开始枚举每一变量内的所有对象,会有多种不同的节点,甚至还会有自己的子数组
            pt_tmp = ptree_root.get_child(v.first);
            BOOST_FOREACH(boost::property_tree::ptree::value_type& vul, pt_tmp)
            {
                //获取枚举到的对象,通过字符串对比,判断相应的字段
                string key_str, vul_str;
                boost::property_tree::ptree p = vul.second;
                key_str = p.front().first;
                vul_str = p.front().second.data();
                if (key_str.compare("名字") == 0)
                {
                    pCharm->strPropName = vul_str;
                }else if (key_str.compare("道具类型") == 0)
                {
                    pCharm->strType = vul_str;
                } else if (key_str.compare("说明") == 0)
                {
                    pCharm->strText = vul_str;
                } else if (key_str.compare("价格") == 0)
                {
                    pCharm->fPrice = boost::lexical_cast<float>(vul_str);
                } else if (key_str.compare("经验值") == 0)
                {
                    pCharm->lDesGetCharm = boost::lexical_cast<long>(vul_str);
                } else if (key_str.compare("主播获得积分") == 0)
                {
                    pCharm->recver_score = boost::lexical_cast<long>(vul_str);
                } else if (key_str.compare("玩家获得积分") == 0)
                {
                    pCharm->sender_score = boost::lexical_cast<long>(vul_str);
                } else if (key_str.compare("返现银子") == 0)
                {
                    pCharm->return_sliver = boost::lexical_cast<long>(vul_str);
                } else if (key_str.compare("货币类型") == 0)
                {
                    pCharm->strMoneyType = vul_str;
                } else if (key_str.compare("特效说明") == 0)
                {
                    pCharm->texiao_str = vul_str;
                } else if (key_str.compare("弹幕次数") == 0)
                {
                    //此节点下面还有n个子对象,需要分别读取并保存到结构体的map中,这里继续枚举当前ptree临时变量,以获取其数组
                    BOOST_FOREACH(boost::property_tree::ptree::value_type& vul, p) //枚举弹幕数组
                    {
                        boost::property_tree::ptree pt_tmp2 = vul.second;
                        //枚举获取所有子对象
                        BOOST_FOREACH(boost::property_tree::ptree::value_type& vul2, pt_tmp2) 
                        {
                            boost::property_tree::ptree p2 = vul2.second;
                            key_str = p2.front().first;
                            vul_str = p2.front().second.data();
                            pCharm->danmu_num[boost::lexical_cast<long>(key_str)] = boost::lexical_cast<int>(vul_str);
                        }
                    }
                } else if (key_str.compare("动画次数") == 0)
                {
                    //此节点下面还有n个子对象,需要分别读取并保存到结构体的map中,这里继续枚举当前ptree临时变量,以获取其数组
                    BOOST_FOREACH(boost::property_tree::ptree::value_type& vul, p)
                    {
                        boost::property_tree::ptree pt_tmp2 = vul.second;
                        //枚举获取所有子对象
                        BOOST_FOREACH(boost::property_tree::ptree::value_type& vul2, pt_tmp2)
                        {
                            boost::property_tree::ptree p2 = vul2.second;
                            key_str = p2.front().first;
                            vul_str = p2.front().second.data();
                            pCharm->donghua_num[boost::lexical_cast<long>(key_str)] = boost::lexical_cast<int>(vul_str);
                        }
                    }
                }
                 _charm_map[charm_id] = pCharm; //将智能指针保存到map容器中
            }
        }

    } catch(boost::property_tree::json_parser::json_parser_error& e) //json解析异常
    {
        const char* err_buf = e.what();
        _charm_map.clear();
        return FALSE;
    } catch (const boost::property_tree::ptree_bad_path& e) //json读取数组或对象时异常
    {
        const char* err_buf = e.what();
        _charm_map.clear();
        return FALSE;
    } catch (const boost::bad_lexical_cast& e) //lexical_cast转换时异常
    {
        const char* err_buf = e.what();
        _charm_map.clear();
        return FALSE;
    } catch (const boost::property_tree::ptree_bad_data& e) //json读取数组或对象时异常
    {
        const char* err_buf = e.what();
        _charm_map.clear();
        return FALSE;
    }
    return TRUE;
}

至此,json就解析完毕了,由于使用了智能指针,所以用户也不用考虑堆内存释放的问题,这个json主要就是嵌套了两层,所以解析起来相对比较麻烦,容易出错。

标签: boost json
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 5
博文 21
码字总数 15419
×
IcedBeer
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: