11月 28 2008

はてなブックマークエントリー情報取得APIのエンコード方式のまずさ

Published by HoLY at 10:20:02 under tech

追記: この件ははてな側で修正済みですので、もう適用する必要はありません。

はてなブックマーク には各エントリー情報、例えばブックマークコメントを取得するための API として はてなブックマークエントリー情報取得API が用意されています。

このAPIが返すJSONがうまく読めなかったので、その記録。

とりあえずこのブログのひとつ前のエントリ自分でブックマークしてみたので、それを取得してみましょう。

http://b.hatena.ne.jp/entry/json/http://holy.enyou.org/2008/11/27/thatsping-is-taken-over/ にアクセスします。現時点ではこんな感じです。(適宜改行を入れてます)

{"count":"1","bookmarks":[{
"comment_raw":"\u00e5\u0088\u00a5\u00e3\u0082\u00a8\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0083\u00aa\u00e3\u0081\u00ae\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0083\u0096\u00e3\u0082\u00af\u00e3\u0083\u009e",
"timestamp":"2008/11/28",
"comment":"\u00e5\u0088\u00a5\u00e3\u0082\u00a8\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0083\u00aa\u00e3\u0081\u00ae\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0083\u0096\u00e3\u0082\u00af\u00e3\u0083\u009e",
"user":"holysugar",
"permalink":"http://b.hatena.ne.jp/holysugar/20081128#bookmark-11024506",
"tags":[]}]}

これを例えば Ruby の JSON.parse で処理してみます。

require 'rubygems'
require 'json'
$KCODE = 'u'
p JSON.parse(open('xxx.json').read)

{"bookmarks"=>[{
"permalink"=>"http://b.hatena.ne.jp/holysugar/20081128#bookmark-11024506", 
"user"=>"holysugar", "timestamp"=>"2008/11/28", "tags"=>[], 
"comment_raw"=>"å¥ã¨ã³ããªã®ããã«ãã¯ã", "comment"=>"å¥ã¨ã³ããªã®ããã«ãã¯ã"}], 
"count"=>"1"}

comment がうまく読めてませんね。

なぜか

はてなブックマーク API では、ASCII 以外の文字をRFC 4627 のJSONの仕様 に従ってエンコードしようとしていると思うのですが、 なぜかコードポイントを表現するのではなく、UTF-8バイト列の各オクテットごとに unicode escape しています。

すなわち、「あ」という文字はコードポイントが U+3042 なため “\u3042″ となるべきですが、 はてブ API では UTF-8 のバイト列を表す “\u00e3\u0081\u0082″ となるっ…。

なんか URL encode で “%e3%81%82″ になってる感じに似てますね。

この問題って?

問題1。とりあえずマトモなパーザではそのまま読めなくて無駄な労力を発揮することができます。:)

問題2。日本語1文字が18バイトになります。ちなみに通常では6バイト、URLエンコードでも9バイトなので、無駄にも程があります。通信量3倍。なんか重いと思ったんだよなあ…。

解決策

はてなが直してくれるのを期待するしかないですが、それまでは置換処理を入れておくのがよさそうです。例えばRubyならこんな感じ?

replaced_json = raw_json_string.gsub(/\\u00([0-9a-f]{2})/i){ $1.to_i(16).chr })
obj = JSON.parse(replaced_json)

\u00xx は正しい処理されてればまず出てこないと期待できるので、これならいつのまにか直っててもOKじゃないかな?

はてなは結構仕様に敏感だと思っていたので、こういうバグ(仕様?)があることは結構意外でした。新はてブリニューアルのせいかもしれない(前からこうだったかは知らない)ので、いつのまにかさっくり直ってるといいなあと期待しています。

はてなアイデア経由で報告

ステータスは変わってないけど、いつのまにか直ってました。bet してくれたみなさんありがとう。

Trackback URI | Comments RSS

Leave a Reply