RJSONIOでUnicode文字列を扱えるようにしてみた
R で JSON を扱うには rjson か RJSONIO がありますが、前者はすぐに落ちるし、後者はバージョン0.4以降 Unicode文字列が扱えないという状況で、実質 R では JSON を扱えません。
twitteR では RJSONIO を使って JSON をパースしているため、twitteR で日本語のツイートを取得するためにはわざわざ RJSONIO 0.3 をダウンロードして手動インストールしなければなりません。
けしからんですね!!
というわけで C/C++ をまともに読むことすらできないのに RJSONIO で Unicode文字列を扱うためのパッチを作成しました。
patch for RJSONIO_0.96-0 ― Gist
パッチを適用して使ってみる
現状把握
とりあえず現状の酷さを確認しておきます
$ R
> install.packages("RJSONIO")
> library(RJSONIO)
> # "あいうえお"
> fromJSON("[\"\\u3042\\u3044\\u3046\\u3048\\u304A\"]")
[1] "BDFHJ"
これはひどいっ!”あいうえお” と表示されませんね!
パッチの適用
$ wget https://raw.github.com/gist/1556388 -O RJSONIO_0.96-0.patch # パッチのダウンロード
$ wget http://cran.r-project.org/src/contrib/RJSONIO_0.96-0.tar.gz # RJSONIO アーカイブのダウンロード
$ tar xvfz RJSONIO_0.96-0.tar.gz
$ patch -p1 -d RJSONIO < RJSONIO_0.96-0.patch
patching file src/libjson/JSONOptions.h
patching file src/rlibjson.c
$ sudo R CMD remove RJSONIO # RJSONIO(バグってるやつ)のアンインストール
$ sudo R CMD install RJSONIO # RJSONIO(パッチを当てたやつ)のインストール
実行してみます
$ R
> library(RJSONIO)
> # "あいうえお"
> fromJSON("[\"\\u3042\\u3044\\u3046\\u3048\\u304A\"]")
[1] "あいうえお"
おおぉぉぉ、ちゃんと “あいうえお” と表示されましたね!!
仕組み
RJSONIO で Unicode文字列が扱えなくなったのは JSONをパースするライブラリを変更したからみたいです。
0.4以降からはlibjsonを使うようにしたみたいなんですが、libjson で Unicode文字列を扱うにはビルド時に libjson/JSONOptions.h の
//#define JSON_UNICODE
となっている部分のコメントアウトを解除しなければなりません。
Unicode文字列を変換する際には
- static_cast
(internalJSONNode) (つまり internalJSONNode::operator json_string()) - internalJSONNode::Fetch
- internalJSONNode::FetchString
- JSONWorker::FixString
- JSONWorker::SpecialChar
と処理されていくのですが、JSON_UNICODEが定義されていると JSONWorker::UTF –> JSONWorker::UTF8 へと処理が渡り、定義されていないといきなり JSONWorker::UTF8 へと処理が渡ります。
これが Unicode文字列を正しくパースするかどうかのポイントです。
っで、JSON_UNICODE を定義すると json_char の型が char* から wchar_t* に変わるので、それに対応させる処理を加えないといけません。
そんなわけで RJSONIO の rlibjson.c を書き換えているんですが、C言語とか全然知らないのでおそらくひどい書き方だと思います・・・
去年RJSONIOの作者にUnicode文字列が扱えないってバグ報告した時は無視されましたが、今度はパッチまで作ったんで何らかの対処をしてくれるでしょう。
これでようやく R でも JSON が扱えるようになるんじゃないですかね!!