文档章节

Boost解析Json字符串

I
 IcedBeer
发布于 2016/12/05 18:29
字数 1336
阅读 161
收藏 1

最近项目中,几年前的配置突然改动了很多, 为了迎合新的修改,故将配置格式由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主要就是嵌套了两层,所以解析起来相对比较麻烦,容易出错。

© 著作权归作者所有

I
粉丝 5
博文 21
码字总数 15419
作品 0
浦东
高级程序员
私信 提问
C++的Json解析库:jsoncpp和boost .

JSON(JavaScript Object Notation)跟xml一样也是一种数据交换格式,了解json请参考其官网http://json.org/,本文不再对json做介绍,将重点介绍c++的json解析库的使用方法。json官网上列出了各...

涩女郎
2015/08/22
166
0
C++的JSON开发包--RapidJSON

Rapidjson 是一个 C++ 的快速 JSON 解析器和生成器,使用 SAX/DOM 风格的 API 设计。 示例代码: // rapidjson/example/simpledom/simpledom.cpp` include "rapidjson/document.h" include "......

MiloYip
2012/02/01
28.4K
5
轻量简单的 C++ JSON 解析库 - ejson

介绍 该库为轻量级的c++ json解析与构造库,源码很短,适合学习,觉得不错的点个star。 提供了的功能: json字符串解析为c++对象(JSONArray和JSONObject) c++对象中获取key-value值 c++对象...

黄泓凯
03/25
670
0
Boost ptree 解析json字符串 多线程下程序crash

今天一个service即将发布之前,用压力测试试了一下,很快就segmentation fault,吓了一身冷汗。 三小时候确定是因为最近几天引入boost::ptree来将解析json的时候出问题。重新自己实现解析代码...

长平狐
2012/08/28
989
0
boost json put int,double保存为string而不能保存int,double的解决方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/byxdaz/article/details/82261018 boost json put int,double保存为string而不能保存int,double的解决方法,...

byxdaz
2018/08/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
今天
6
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
今天
6
0
【技术分享】TestFlight测试的流程文档

上架基本需求资料 1、苹果开发者账号(如还没账号先申请-苹果开发者账号申请教程) 2、开发好的APP 通过本篇教程,可以学习到ios证书申请和打包ipa上传到appstoreconnect.apple.com进行TestF...

qtb999
今天
10
0
再见 Spring Boot 1.X,Spring Boot 2.X 走向舞台中心

2019年8月6日,Spring 官方在其博客宣布,Spring Boot 1.x 停止维护,Spring Boot 1.x 生命周期正式结束。 其实早在2018年7月30号,Spring 官方就已经在博客进行过预告,Spring Boot 1.X 将维...

Java技术剑
今天
17
0
浅谈java过滤器Filter

一、简介 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断如是否有权限访问页面等。其工作原理是,只要你在web.xml...

青衣霓裳
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部