免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6765 | 回复: 3
打印 上一主题 下一主题

[C] [转] 用 JSON 保存后台配置数据 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-03-09 12:53 |只看该作者 |倒序浏览
本帖最后由 newzy 于 2011-03-09 13:00 编辑

用 JSON 保存后台配置数据

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/newzy/archive/2011/03/08/6232832.aspx

在前台数据交换中,优其 web应用领域,JSON以其简单性和可扩展性“大有替代”xml 之势(夸张地说)。
本文简单介绍了 json 作为配置的存取在后台操作的便利性,希望本文能抛砖引玉,让JSON给大家后台配置存取提供更多便利。


编辑器: JSON 在线编辑器 JsonEditor V1.03.2


在一些中/小型应用程序中,配置文件是必须的。采用什么格式的配置文件一直困扰着很多开发人员。实践中常用的有四种类型:
1) 采用 c/c++ 的结构体存储。

      虽然很原始,便还是在很多场景可以看到,原因是免解析。缺点太多了,比如不易扩展,可读性差。

2)采用 "名称 = 值" 的行存储,或类似 windows 系统 ini 文件的格式。 通过 xxx_set/xxx_get 的方法进行存取.

     在各种应用中都很常见,优其小型嵌入式设备上很多时候配置采用类似的方法。

3)采用相对复杂的分段/分级配置。

     如 Apache/Ngix 等的配置文件,再如 cisco 的 consle 配置。优点时文本方式,便于编辑,有良好的结构性。

     缺点解析起来相对复杂,需要为应用定制配置格式。

4)采用 xml 格式保存配置。

     在大型应用,优其 java,.net 的项目中应用的优其多。原因是平台或操作语言提供了 xml 的操作 API。

     在小型 c/c++ 程序中, 如果你有 DOM/XML 的操作 API, 依然是是可行的。

最近在一些小型项目的实践中, 保存配置文件,我是越来越倾向于使用 JSON 了。原因是
1) JSON 像 XML  一样有的良好结构性。

2) JSON 固有的数据类型 object/string/number/true/false 意义明确,便于表达.

3) JSON 语法简单,解析器易实现,同时便于解析和格式化输出。(JSON的官方站点上有各种语言的解析器)

4) 配置层次性好,最近又修改了一个开源 JSON "树型" 编辑器。用工具编辑配置文件,感觉很省事。

说了这多, 还未到正文。下来用示例来说明下吧。后文件示例以 c 代码作为伪代码展示。
假设你已经有如下 JSON 的操作 API (如果没有可以很容易自己实现封装):

1)  json_t   /*json 类型 */

2)  json_t * json_parse_string(const char * json_string);   /* 解析 json 树 */
3)  const char * json_get_name(json_t * json, const char * path); /* 获取节点名 */
4)  const char * json_get_str(json_t * json, const char * path); /* 获取节点值:string  类型 */
5)  const char * json_get_int(json_t * json, const char * path); /* 获取节点值:int 类型 */
6) FOREACH_IN_JSON_CHILD(json, path, pchild) /* 宏用于遍历子节点 */

   

以下为假想配置示例:

  1. {   
  2.     "Root":"F:/website/doc",   
  3.     "Connection":{   
  4.         "maxconnects":1500,   
  5.         "maxkeepalive":0,   
  6.         "keeptimeout":15,   
  7.     },   
  8.     "Listen":[{   
  9.             "ip":"0.0.0.0",   
  10.             "port":"8088",   
  11.             "protocol":"http",   
  12.             "maxlisten":"100"  
  13.         },   
  14.         {   
  15.             "ip":"127.0.0.1",   
  16.             "port":"8090",   
  17.             "protocol":"http",   
  18.             "maxlisten":"100"  
  19.         }],   
  20.     "Directory":{   
  21.         "/app/":{   
  22.             "path":"F:/website/doc",   
  23.             "RewriteRule":[{   
  24.                     "from":"",   
  25.                     "to":"{}"  
  26.                 },   
  27.                 {   
  28.                     "from":"",   
  29.                     "to":"{}"  
  30.                 }]   
  31.         },   
  32.         "/libso/":{   
  33.             "path":"E:/eybuild/lib6/app/",   
  34.             "RewriteRule":[{   
  35.                     "from":"",   
  36.                     "to":"{}"  
  37.                 },   
  38.                 {   
  39.                     "from":"",   
  40.                     "to":"{}"  
  41.                 }]   
  42.         },   
  43.         }   
  44.     },   
  45.     "DAction":[   
  46.         "/libso/*.so",   
  47.         "/libso/*.dll",   
  48.         "/dll/*.dll"],   
  49.     "SAction":[   
  50.         "/app/**",   
  51.         "/bbr/",   
  52.         "/cplus/"],   
  53.     "Log":{   
  54.         "Logfile":"c:/log/log.log",   
  55.         "Loglevel":5   
  56.     }   
  57. }  
  58. {
  59.     "Root":"F:/website/doc",
  60.     "Connection":{
  61.         "maxconnects":1500,
  62.         "maxkeepalive":0,
  63.         "keeptimeout":15,
  64.     },
  65.     "Listen":[{
  66.             "ip":"0.0.0.0",
  67.             "port":"8088",
  68.             "protocol":"http",
  69.             "maxlisten":"100"
  70.         },
  71.         {
  72.             "ip":"127.0.0.1",
  73.             "port":"8090",
  74.             "protocol":"http",
  75.             "maxlisten":"100"
  76.         }],
  77.     "Directory":{
  78.         "/app/":{
  79.             "path":"F:/website/doc",
  80.             "RewriteRule":[{
  81.                     "from":"",
  82.                     "to":"{}"
  83.                 },
  84.                 {
  85.                     "from":"",
  86.                     "to":"{}"
  87.                 }]
  88.         },
  89.         "/libso/":{
  90.             "path":"E:/eybuild/lib6/app/",
  91.             "RewriteRule":[{
  92.                     "from":"",
  93.                     "to":"{}"
  94.                 },
  95.                 {
  96.                     "from":"",
  97.                     "to":"{}"
  98.                 }]
  99.         },
  100.         }
  101.     },
  102.     "DAction":[
  103.         "/libso/*.so",
  104.         "/libso/*.dll",
  105.         "/dll/*.dll"],
  106.     "SAction":[
  107.         "/app/**",
  108.         "/bbr/",
  109.         "/cplus/"],
  110.     "Log":{
  111.         "Logfile":"c:/log/log.log",
  112.         "Loglevel":5
  113.     }
  114. }

复制代码
1) 加载配置文件,解析成 JSON 树.

      readfile(conf_buf, from_file);     /*加载配置 */

      json_t * jcon = json_parse_string(conf_buf);

2)遍历第一层配置。

     json_t *  jobj;

    FOREACH_IN_JSON_CHILD(jconf, "", jobj)

    {

          const char * pname = json_get_name(jobj));

          const char * pvalue = json_get_str(jobj);

          if (compare("Root", pname))

              call_xxx_set_root(); /* 把值传给处理函数 */

          else if (compare("Connection", pname))

              call_xxx_set_connection(); /* 把值传给处理函数 */

          else if (compare("Listen", pname))

              call_xxx_set_listen(jobj); /* 把值传给处理函数 */

         ....  /* 其它节点 */

    }

3)对子节点进行处理,以 Listen 数组下的结点为例。

     从上面我们可以看到 Listen是个数组,其下的节点数目是不确定的,依然使用 foreach 的形式进行遍历.

    int call_xxx_set_lisen(json_t * jconf)

    {

         json_t *  jobj;

         /* 从数组中取出一个节点 */

         FOREACH_IN_JSON_CHILD(jconf, "", jobj)

         {

               /* 对数组中的每一个原素 */

               const char * ip = json_get_name(jobj, "ip"));

               short int  port  = json_get_int(jobj, "port");

              ....  /* 这里加上应用该配置的函数 */

          }

    }

4)其它节点类似。

小结:

JSON 的如下特性决定了 json 非常适合配置存储:

1) JSON 具有良好的树型结构,便于程序操作。

2) JSON 对像的值可以是一个普通对象也可以是一个“集合”或数组,使用FOREACH_IN_JSON_CHILD()的形式对子节点遍历。

3) JSON 对象便于序列化成字符串存储/传递.

4) JSON 便于解析/格式化

5) 因为天太晚了该睡了,此处略去 nK 字吧, 呵呵



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/newzy/archive/2011/03/08/6232832.aspx

论坛徽章:
0
2 [报告]
发表于 2011-03-09 21:30 |只看该作者
呵呵,我看行!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2011-03-09 22:08 |只看该作者
本帖最后由 flw 于 2011-03-09 22:13 编辑

JSON 很不错。不过貌似和 YAML 是同构的。我一直都在用 YAML。

哦,YAML is a superset of JSON。

论坛徽章:
0
4 [报告]
发表于 2012-03-15 10:51 |只看该作者
过来学习一下,因为最近在用JSON,感觉的确很好用,
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP