当前位置: 首页 > news >正文

修复libjson不支持utf8格式字符

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

libjson支持中文显示,但要是你使用\u格式的utf8字符串,那解析就会出问题,百度谷歌了很久都没找到解决方法。后来找到了一篇文章,里面有提解决方法,但我没成功。既然知道了问题所在,就自己写吧。

libjson可以处理UNICODE,但使用了wchar_t,而开发当中大多使用char,这就造成了很多的不兼容。如果不开启UNICODE,"\uXXXX"之类的字符,libjson会舍弃前2位.

问题出在JSONWorker.cpp的SpecialChar函数里面

1
2
3
4
5
6
7
8
9
    case  JSON_TEXT( 'u' ):  //utf character
        {
         #ifdef JSON_UNICODE
            UTF(pos, res, end);
         #else
           UTF8(pos,res, end);
         #endif
        }
      break ;

UTF8函数

1
2
3
4
5
6
7
8
9
10
11
12
json_uchar JSONWorker::UTF8( const  json_char * & pos,  const  json_char *  const  end) json_nothrow {
     JSON_ASSERT_SAFE((( long )end - ( long )pos) > 4, JSON_TEXT( "UTF will go out of bounds" ),  return  JSON_TEXT( '\0' ););
     #ifdef JSON_UNICODE
        ++pos;
        json_uchar temp = Hex(pos) << 8;
        ++pos;
        return  temp | Hex(pos);
     # else
     pos+=3;
     return  Hex(pos);
     #endif
}

这里可以看到,如果不开启JSON_UNICODE,会将"\uXXXX"中的前2位忽略掉了,ASCII当然是正确的,但非ASCII就会出问题了。

于是我增加了几个函数Hex2UTF8,String2Hex,UTF83B,DChar2Short

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
                 std::string Hex2UTF8( const  json_char* & pos, const  json_char *  const  end)
         {
             JSON_ASSERT(*(pos + 1) == JSON_TEXT( '0' ), JSON_TEXT( "wide utf character (hihi)" ));
             JSON_ASSERT(*(pos + 2) == JSON_TEXT( '0' ), JSON_TEXT( "wide utf character (hilo)" ));
             //截取字符串
             ++pos;
             
             int  len=4;
             char  * str=( char *) malloc (len+1);
             bzero(str, len+1);
             memcpy (str, pos, len);
             str[len]=0;
             pos+=3;
             //保留原始指针
             char * pstr=str;
             
             std::string rstr;
             if  (*pstr==JSON_TEXT( 'u' )) {       //u
                 pstr++;
             } else  if (*pstr==JSON_TEXT( '\\' )){   //\u
                 pstr+=2;
             }
             char  hexStr[5]={0};
             memcpy (hexStr, pstr, 4);
             unsigned  short  hex=String2Hex(hexStr);
             if  (hex<0x0800 ||hex>0xFFFF) {
                 JSON_ASSERT(1, JSON_TEXT( "now only support hex >0x0800 's utf8 char" ));
                 return  "" ;
             }
             rstr+=UTF83B(hex);
             free (str);
             str=NULL;
             return  rstr;
         }      
1
2
3
4
5
6
7
8
9
10
11
12
std::string UTF83B(unsigned  short  hex)
{
     unsigned  char  hc=((hex&0xF000)>>12);     //取前4位
     unsigned  char  mc=((hex & 0x0FC0)>>6);  //取中间6位
     unsigned  char  lc=(hex & 0x003F);         //取后6位
     char  str[4]={0};
     str[0]=(0xE0 | hc);
     str[1]=(0x80 | mc);
     str[2]=(0x80 | lc);
     std::string rstr=str;
     return  rstr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
         unsigned  short  String2Hex( const  json_char* str)
     {
         unsigned  short  hex=0x0000;
         unsigned  short  hi=0;
         unsigned  short  lo=0;
         unsigned  short  len= strlen (str);
         if  (len==2) {
             lo=DChar2Short(str);
         }
         else  if (len==4)
         {
             hi=DChar2Short(str);
             lo=DChar2Short(str+2);
         }
         
         hex=(((hi<<8) &0xFF00) |(lo & 0x00FF));
         
         return  hex;
     }      
    


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
unsigned  short  Char2Short(json_char c)
{
     unsigned  short  ret = 0;
     switch  (c) {
     case  'A' :
     case  'a' :
         ret = 10;
         break ;
     case  'B' :
     case  'b' :
         ret = 11;
         break ;
     case  'C' :
     case  'c' :
         ret = 12;
         break ;
     case  'D' :
     case  'd' :
         ret = 13;
         break ;
     case  'E' :
     case  'e' :
         ret = 14;
         break ;
     case  'F' :
     case  'f' :
         ret = 15;
         break ;
     default :
         ret = c -  '0' ;
         break ;
     }
     return  ret;
}


1
2
3
4
5
6
7
8
9
10
11
unsigned  short  DChar2Short( const  json_char* str)
{
     unsigned  short  ret=0;
     unsigned  short  hi=0;
     unsigned  short  lo=0;
     
     hi=Char2Short(str[0]);
     lo=Char2Short(str[1]);
     ret=hi*16+lo;
     return  ret;
}

然后,在SpecialChar函数里面修改

1
2
3
4
5
6
7
    case  JSON_TEXT( 'u' ):  //utf character
       #ifdef JSON_UNICODE
          UTF(pos, res, end);
       # else
          res += Hex2UTF8(pos, end);
       #endif
       break ;

还有就是不能开启JSON_ESCAPE_WRITES,不然会失效。

注:

我只是测试了从\uxxxx出来,但没测试从原字符串转换到\u。


转载于:https://my.oschina.net/JeremyOuyang/blog/189781

相关文章:

  • 表空间在dba_tablespaces中存在,删除时却提示无法删除
  • MyEclipse 安装aptana插件
  • DZ论坛如何去掉“今日”“昨日”发帖数显示?
  • PHP+MYSQL 出现乱码的解决方法
  • mysql 按距离今日时间最近排序
  • Ruby小例子
  • MySQL安装方法及简单配置
  • 【好文翻译】码农们:效率与质量,你选择哪个?
  • [转]div 让文字或图片居中
  • 程序员能力矩阵 Programmer Competency Matrix
  • 【英文演讲】What are your strengths
  • Android 提示应用“正在发送大量短信”的解决办法
  • ESXi 5.1如何將多個vmdk映像檔轉換成一個
  • Smart2.0开发指南——开发工具
  • poj 1470(简单LCA 倍增法)
  • 【comparator, comparable】小总结
  • 4个实用的微服务测试策略
  • Java多线程(4):使用线程池执行定时任务
  • js对象的深浅拷贝
  • js作用域和this的理解
  • Material Design
  • node.js
  • node学习系列之简单文件上传
  • Odoo domain写法及运用
  • tweak 支持第三方库
  • 七牛云假注销小指南
  • 前端自动化解决方案
  • 入口文件开始,分析Vue源码实现
  • 消息队列系列二(IOT中消息队列的应用)
  • 一份游戏开发学习路线
  • 责任链模式的两种实现
  • 怎样选择前端框架
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #预处理和函数的对比以及条件编译
  • (11)MSP430F5529 定时器B
  • (3)(3.5) 遥测无线电区域条例
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (七)Knockout 创建自定义绑定
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转) 深度模型优化性能 调参
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)重识new
  • .Net CF下精确的计时器
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET 反射的使用
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .NET开发人员必知的八个网站
  • .net下的富文本编辑器FCKeditor的配置方法
  • .net中生成excel后调整宽度
  • .php结尾的域名,【php】php正则截取url中域名后的内容