RubyのJSONライブラリは1.4系でescape周りで変更があった

けど騒ぐことではなかった。

でも JS との相互運用考えると \u 形式の escape してた方がいいっぽい。待て続報。

RFC に may って書いてあったので問題解決というか問題は存在しなかった

Twitter / mala: 実装依存(できる、してもよい、しなくてもいい)でしょ …

なるほど。

http://tools.ietf.org/html/rfc4627

Any character may be escaped. If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. The hexadecimal letters A though F can be upper or lowercase. So, for example, a string containing only a single reverse solidus character may be represented as "\u005C".

ということで、escape されるとは限りませんよ、で何の問題もないのであった。

背景とまとめ

REE ( Ruby 1.8.7 ) + json 1.4.6 の環境で Hash#to_json を使っていくらシリアライズしてやっても日本語がエスケープされずに出力されてしまう。最初のうちはあまりに自然で気づかなかったけど、いやいや、JSON は生で読めないはずだと思い出してからはそれが再現できずにずいぶんと悩んでしまった。※ 思い出したというか思い込んだっつーことでした。

json のバージョンを戻せば直るかと思ってやったら確かに期待する動作になったけれど、これもしかして Ruby 1.9 を期待して内部をいじって失敗したクチじゃねーのと思い直して実験してみた。

結果、Ruby のバージョンによらず全部同じ動作をした。

実験に利用したRuby

$ rvm list

rvm rubies

   rbx-1.0.1-20100603 [ ]
   ruby-1.8.7-p299 [ i386 ]
   ruby-1.9.2-head [ i386 ]

実験に利用したgem

  • json 1.2.4
  • json 1.4.6

実験結果 json 1.4.6

$ rvm ruby json14.rb

info: rbx-1.0.1-20100603: rubinius 1.0.1 (1.8.7 release 2010-06-03 JI) [i686-apple-darwin9.8.0]

{
  "key1": "あいう",
  "key2": "漢字"
}

info: ruby-1.8.7-p299: ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-darwin9.8.0]

{
  "key1": "あいう",
  "key2": "漢字"
}

info: ruby-1.9.2-head: ruby 1.9.2p14 (2010-10-02 revision 29393) [i386-darwin9.8.0]

{
  "key1": "あいう",
  "key2": "漢字"
}

実験結果 json 1.2.4

$ rvm ruby json12.rb

info: rbx-1.0.1-20100603: rubinius 1.0.1 (1.8.7 release 2010-06-03 JI) [i686-apple-darwin9.8.0]

{
  "key1": "\u3042\u3044\u3046",
  "key2": "\u6f22\u5b57"
}

info: ruby-1.8.7-p299: ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-darwin9.8.0]

{
  "key1": "\u3042\u3044\u3046",
  "key2": "\u6f22\u5b57"
}

info: ruby-1.9.2-head: ruby 1.9.2p14 (2010-10-02 revision 29393) [i386-darwin9.8.0]

{
  "key1": "\u3042\u3044\u3046",
  "key2": "\u6f22\u5b57"
}

ね? やっぱ変じゃない?変じゃないよ!

RFC のバージョンが上がって日本語もエスケープしなくてよくなったの?最初からescapeする「必要」はありませんでした。

また当たり前ですが parse はどちらの形式できても問題なくできました。

実験に使ったコード

json12.rb

#! /usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'rubygems' unless defined? ::Gem
gem 'json', '< 1.4'
require 'json'

require File.dirname( __FILE__ ) + '/body'

json14.rb

#! /usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'rubygems' unless defined? ::Gem
gem 'json', '>= 1.4'
require 'json'

require File.dirname( __FILE__ ) + '/body'

body.rb

# -*- coding: utf-8 -*-

jj ( { 'key1' => 'あいう',
       'key2' => '漢字'
     } )

余談

rvm list の platform の情報と実際に実行したときに出てくる情報が食い違ってるなぁ。

More