ホーム DoRuby json の憂鬱

json の憂鬱

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

現在ではxmlよりもyml よりも使われているであろう構造化文書の形式json。自分がド新人だったときに、「json? なんて不吉な名前の変数なんだ」と思ったのも遠い昔のことです。

json を始めとする構造化文書の便利さは、適切なライブラリを使えば 言語内の変数(hash, array 等)⇔一般的なテキスト、の変換が 容易に行えることにあります。

データを RDB に保存するとき、変数の構造が変化したとしても、 カラムを増やしたり join を行ったりせず、その項目での検索を ある程度あきらめるのであれば、容易かつ高速に、多様な形式の データを保存できます

class Samples < ActiveRecord::Migration
  def self.up
    create_table :samples do |t|
    t.string “name”
    t.text “description”
    t.text “parms_json” #ここに、詳しいデータを json 化して保存する
  end
  def self.down
    drop_table :samples
  end

で、ここの「params_json」の値ですが、上の値に関しては、 サーバサイド(Ruby on Rails)で生成した場合と クライアントサイド(Ajax)で生成した場合と、 同じ形式で保存されることが期待されるのですが、 こちら、ちょっと困った「クセ」がそれぞれありました。 そのクセの内容と、対策を共有します。

0) まずはスタート

下記のような変数を(ruby の記法)

hash = {
    :a => “b”, :c => [ [“あ”, “い”, “う”], [“え”, “お”, “か”] ]
}

を、

{ “a”:”b”, “c”:[ [“あ”,”い”,”う”], [“え”,”お”,”か”] ] }



という json にしたい。

1) Ruby on Rails の場合

何も考えずに hash.to_json した場合、

>> hash.to_json => “{\”a\”:\”b\”,\”c\”:[[\”\\u3042\”,\”\\u3044\”,\”\\u3046\”],[\”\\u3048\”,\”\\u304a\”,\”\\u304b\”]]}”

のように、 unicode_escape されて出力されます。 こちら、escape されて欲しくない場合、下記のような関数を作成し 出力を得ます。

    def json_unescape(str)
      str.gsub(/\\([\\\/]|u[0-9a-fA-F]{4})/) do
        ustr = $1
        if ustr.starts_with?(‘u’)
          [ustr[1..-1].to_i(16)].pack(“U”)
        elsif ustr == ‘\\’
          ‘\\\\’
        else
          ustr
        end
      end
    end

出力は

>> json_unescape(hash.to_json) => “{\”a\”:\”b\”,\”c\”:[[\”あ\”,\”い\”,\”う\”],[\”え\”,\”お\”,\”か\”]]}”

2) jquery-json の場合

jquery および jquery-json を読み込んだ環境下にて、

alert(jQuery.toJSON({a:”b”, c:[[“あ”, “い”, “う”], [“え”, “お”, “か”]]}));

を実行したら、

{“a”:”b”,”c”:”[[\”あ\”, \”い\”, \”う\”], [\”え\”, \”お\”, \”か\”]]”}

のように、配列が内部でエスケープされた状態で出力されます。 上記のエスケープを解除したい場合、下記のような処理になります。

function no_escape_to_json(obj) {
  return jQuery.toJSON(obj).replace(/\\\”/g, “\””).replace(/\”\[/g, “\[“).replace(/\]\”/g, “\]”);
}

1), 2) の処理とも、アドホックな対応のため、あまり推奨されないやり方になります。が、もしお困りの方がいればご参考いただきたいな、と。 また、もっと根本的なスマートなやり方がある場合、お教えいただけますと幸いです。

記事を共有

最近人気な記事