cJSON を使用して JSON 文字列を解析すると、中国語の文字に余分な「\」が表示される

一部の特殊な中国語文字の場合は、cJSON_AddItemToObject を使用してキーと値のペアを追加し、cJSON_Print を使用して印刷します。取得された中国語文字の後には複数の文字「\」が続きます。

追跡により、解析中に漢字の 1 バイト処理が実行されたことが判明したため、2 バイト処理に修正する必要があります。コードは次のように変更されます。

ファイル: cJSON.c

/* 提供された cstring を、印刷可能なエスケープ バージョンにレンダリングします。*/
static char *print_string_ptr(const char *str,printbuffer *p)
{
const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char トークン;

for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\') )?1:0;
if (!フラグ)
{
len=ptr-str;
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) は 0 を返します。
ptr2=out;*ptr2++='\"';
strcpy(ptr2,str);
ptr2[len]='\"';
ptr2[len+1]=0;
出て行きます。
}

if (!str)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (!out) は 0 を返します。
strcpy(out,"\"\"");
出て行きます。
}
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32 ) len+=5;ptr++;}

if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) は 0 を返します。


ptr2=out;ptr=str;
*ptr2++='\"';

その間 (*ptr)
{
int m=strlen(ptr);
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
{
if (*ptr < 0) // 漢字は一度に 2 バイト処理する必要があります
{
*ptr2++=*ptr++;
*ptr2++=*ptr++;
}

}
それ以外
{
*ptr2++='\\';
スイッチ (token=*ptr++)
{
ケース '\\': *ptr2++='\\'; 壊す;
case '\"': *ptr2++='\"'; 壊す;
ケース '\b': *ptr2++='b'; 壊す;
ケース '\f': *ptr2++='f'; 壊す;
ケース '\n': *ptr2++='n'; 壊す;
ケース '\r': *ptr2++='r'; 壊す;
ケース '\t': *ptr2++='t'; 壊す;
デフォルト: sprintf(ptr2,"u%04x",token);ptr2+=5;壊す; /* エスケープして出力します */
}
}
}


*ptr2++='\"';*ptr2++=0;
出て行きます。
}


同様に、JSON 文字列からのキーと値のペアの解析にも特別な処理が必要です。

static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* 文字列ではありません! */

while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* エスケープされた引用符をスキップします。 */

out=(char*)cJSON_malloc(len+1); /* これは、大まかに言うと、文字列に必要な長さです。*/
if (!out) は 0 を返します。

ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\')
{
if (*ptr < 0) 
{
*ptr2++=*ptr++;

*ptr2++=*ptr++;
}
それ以外
{
ptr++;
スイッチ (*ptr)
{
ケース 'b': *ptr2++='\b'; 壊す;
ケース 'f': *ptr2++='\f'; 壊す;
ケース 'n': *ptr2++='\n'; 壊す;
ケース 'r': *ptr2++='\r'; 壊す;
ケース 't': *ptr2++='\t'; 壊す;
case 'u': /* utf16 を utf8 にトランスコードします。*/
uc=parse_hex4(ptr+1);ptr+=4; /* Unicode 文字を取得します。*/


if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) ブレーク; /* 無効かどうかをチェックします。 */


if ( uc >= 0xD800 && uc <= 0xDBFF ) /* UTF16 サロゲート ペア。 */
{
if (ptr[1]!='\\' || ptr[2]!='u') ブレーク; /* サロゲートの後半が欠落しています。 */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) ブレーク; /* サロゲートの後半が無効です。 */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}


len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=長さ;

スイッチ (長さ) {
ケース 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=長さ;
壊す;
デフォルト: *ptr2++=*ptr; 壊す;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
項目->値文字列=アウト;
item->type=cJSON_String;
ptr を返します。
}

static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* 文字列ではありません! */

while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* エスケープされた引用符をスキップします。 */

out=(char*)cJSON_malloc(len+1); /* これは、大まかに言うと、文字列に必要な長さです。*/
if (!out) は 0 を返します。

ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\')
{
if (*ptr < 0) // 漢字は一度に 2 バイト処理する必要がある 20171110
{
*ptr2++=*ptr++;
*ptr2++=*ptr++;

*ptr2++=*ptr++;
}
それ以外
{
ptr++;
スイッチ (*ptr)
{
ケース 'b': *ptr2++='\b'; 壊す;
ケース 'f': *ptr2++='\f'; 壊す;
ケース 'n': *ptr2++='\n'; 壊す;
ケース 'r': *ptr2++='\r'; 壊す;
ケース 't': *ptr2++='\t'; 壊す;
case 'u': /* utf16 を utf8 にトランスコードします。*/
uc=parse_hex4(ptr+1);ptr+=4; /* Unicode 文字を取得します。*/


if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) ブレーク; /* 無効かどうかをチェックします。 */


if ( uc >= 0xD800 && uc <= 0xDBFF ) /* UTF16 サロゲート ペア。 */
{
if (ptr[1]!='\\' || ptr[2]!='u') ブレーク; /* サロゲートの後半が欠落しています。 */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) ブレーク; /* サロゲートの後半が無効です。 */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}


len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=長さ;

スイッチ (長さ) {
ケース 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=長さ;
壊す;
デフォルト: *ptr2++=*ptr; 壊す;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
項目->値文字列=アウト;
item->type=cJSON_String;
ptr を返します。
}

static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* 文字列ではありません! */

while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* エスケープされた引用符をスキップします。 */

out=(char*)cJSON_malloc(len+1); /* これは、大まかに言うと、文字列に必要な長さです。*/
if (!out) は 0 を返します。

ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\')
{
if (*ptr < 0) // 漢字は一度に 2 バイト処理する必要がある 20171110
{
*ptr2++=*ptr++;
*ptr2++=*ptr++;

*ptr2++=*ptr++;
}
それ以外
{
ptr++;
スイッチ (*ptr)
{
ケース 'b': *ptr2++='\b'; 壊す;
ケース 'f': *ptr2++='\f'; 壊す;
ケース 'n': *ptr2++='\n'; 壊す;
ケース 'r': *ptr2++='\r'; 壊す;
ケース 't': *ptr2++='\t'; 壊す;
case 'u': /* utf16 を utf8 にトランスコードします。*/
uc=parse_hex4(ptr+1);ptr+=4; /* Unicode 文字を取得します。*/


if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) ブレーク; /* 無効かどうかをチェックします。 */


if ( uc >= 0xD800 && uc <= 0xDBFF ) /* UTF16 サロゲート ペア。 */
{
if (ptr[1]!='\\' || ptr[2]!='u') ブレーク; /* サロゲートの後半が欠落しています。 */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) ブレーク; /* サロゲートの後半が無効です。 */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}


len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=長さ;

スイッチ (長さ) {
ケース 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
ケース 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=長さ;
壊す;
デフォルト: *ptr2++=*ptr; 壊す;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
項目->値文字列=アウト;
item->type=cJSON_String;
ptr を返します。
}

おすすめ

転載: blog.csdn.net/Smile_king/article/details/78497088