LoginSignup
1
1

More than 5 years have passed since last update.

JSONのユニコードエスケープ処理にICUを使用する

Last updated at Posted at 2018-09-29

ユニコードエスケープの対応

JSON形式では、GETやPOSTでWebサーバーに要求を送ると日本語の文字列は下の例のようにユニコードエスケープ処理されて返ってきます。

Json文字列の一部
"Type":"A10","Code":"9876","Name":"\u3053\u3093\u306b\u3061\u306f"

上の例にある先頭の/u3053は日本語の「こ」で16ビットのコードポイントです。5文字をあわせて「こんにちは」になります。

コードポイントをC/C++で日本語にする場合、大変高度なCの知識が必要になりコード量が増加します。これを回避するため、ICUを使います。

ICUを使えば、Web時代でのWindowsアプリケーションのプログラミングが楽になると思います。

What is ICU?

International Components for Unicodeを略し、ICUと呼びます。ユニコードを扱うオープンソースライブラリーです。

C/C++、JAVAでこのライブラリーを利用してアプリケーションが作成できます。世界の大手IT企業がICUを利用してアプリケーションを作成しています。

これまでに広範に利用され続け、成熟された内容に進化し続けています。いまでも頻繁にアップデートされている。

ダウンロードと環境構築

PCの環境としてWindows10,Visual Studio 2017を前提にしています。

ICUのソースコードをホームページのダウンロードサイトからダウンロードします。
ICU4CがC用のソースです。
ICU4C Source Code Downloadの項目からZIP file for Windows platformsを選びます。
ファイル名はicu4c-62_1-src.zipですが、62_1はリリース番号です。
git-hubの場合、こちらダウンロードしてください。

ダウンロードしたら任意のフォルダーに解凍し、icuフォルダーがあるのを確認します。
そのなかにあるsourceフォルダーのallinoneというフォルダーを開き、Visual studioでソリューションファイル「allinone.sln」を開きます。開いたらリリースモードでビルドします。

ビルドが完了するとicuフォルダーの直下にlib、 binフォルダーがそれぞれ作成されます。
今度はicuフォルダーをCドライブ直下に移動させます(フォルダーの置き場所は任意の場所でOkです)。

pathを通すため、windowsの環境変数のpathの項目にc:\icu\binを追加します。

ICUを使用したいプロジェクトを作り、プロパティ→リンカー→入力→追加の依存に次のファイルを追加します。

追加の依存ファイル(コピペしてください)
icuuc.lib;icuin.lib

linker.png

同じくライブラリーディレクトリにc:\icu\libとインクルードディレクトリにC:\icu\includeを追加します。

無題.png

プロジェクトフォルダのソースファイル(cpp/cファイル)のある場所に以下のファイルをicuフォルダーからコピー&ペーストします。

以下のファイルをプロジェクトフォルダーにコピペする

icuin62.dll
icuuc62.dll
icudt62.dll

Coding with C

今回はCにてユニコードのコードポイントからCString型に変換します。

Coding_With_C
// Visual C++ の CLR、 CLR empty projectで作成。
// Visual StudioからMFC関連のAPIを導入してください。

#include <atlstr.h>
#include <unicode\unistr.h> // ICUのヘッダーを追加する。

int main() {

// WEBサーバーからのJSON形式のレスポンスの一部。(constにはできない文字列。)
    char src[] = "\"Type\":\"A10\",\"Code\":\"9876\",\"Name\":\"\\u3053\\u3093\\u306b\\u3061\\u306f\"";
    char separator[] = "\\u"; //区切り文字をセット。
    char dq[] = "\"";
    char targetWord[] = "Name\":\""; // ターゲットとなる項目の文字列を選ぶ。
    char* pSrc = NULL;
    char* gotWord = NULL;
    char* answer = NULL;
    char* token = NULL;
    char temp[256];
    icu::UnicodeString uniStr;
    CString strCstr;
    HWND hWnd = NULL;

    pSrc = strstr(src, targetWord); // ターゲットの文字列の先頭にポインターを移す。
    pSrc += strlen(targetWord); // ターゲット項目の文字列の数だけポインターをずらす。
    gotWord = strtok_s(pSrc, dq, &token);// ポインター位置からダブルクオーテーションまでの文字を抜き出す。

    answer = strtok_s(gotWord, separator, &token);//区切り文字を「\\u」として、文字列を抽出する。
    while (answer != NULL) {

        strcpy_s(temp, sizeof(temp), "0x");
        strcat_s(temp, sizeof(temp), answer); //文字列を0xXXXXに変換する。
        uniStr = strtol(temp, NULL, 16); // ICUのUnicodeStringに16進数へ変換した文字を入れる。
        strCstr.AppendFormat(_T("%s"), uniStr.getTerminatedBuffer()); // CString形式に変換して文字を追加する。

        answer = strtok_s(NULL, separator, &token);//次の文字列を探す。
    }

    MessageBox(hWnd, strCstr, _T("Message"), MB_OK | MB_ICONINFORMATION);//メッセージを表示する。

    return 0;
}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1