修復libjson不支持utf8格式字符

libjson支持中文顯示,但要是你使用\u格式的utf8字符串,那解析就會出問題,百度谷歌了好久都沒找到解決方法。後來找到了一篇文章,裏面有提解決方法,但我沒成功。既然知道了問題所在,就本身寫吧。
json

libjson能夠處理UNICODE,但使用了wchar_t,而開發當中大多使用char,這就形成了不少的不兼容。若是不開啓UNICODE,"\uXXXX"之類的字符,libjson會捨棄前2位.ide

問題出在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就會出問題了。spa

因而我增長了幾個函數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函數裏面修改code

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,否則會失效。ci

注:開發

我只是測試了從\uxxxx出來,但沒測試從原字符串轉換到\u。字符串

相關文章
相關標籤/搜索