環境
* MacBook Air MC506J/A
* ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10]
MacBook Air にて RubyGems を使って JSON ライブラリをインストール。
$ sudo gem install json
Successfully installed json-1.5.0
インストールされたライブラリはこれ ⇒ JSON implementation for Ruby
Ruby 1.9系には標準添付ライブラリとしてこのJSONライブラリが付いてくるらしく、日本語に訳されたドキュメントがある。
Ruby 1.9.2 リファレンスマニュアル ⇒ library json
で、どんなデータを渡せばいいのか使い方がよくわからなかったのでJSON文字列を生成するサンプル的なコードを書いてみた。
$ cat ./jsonsample.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'json'
def output(json_data)
json_str_1 = JSON.generate(json_data)
json_str_2 = JSON.pretty_generate(json_data)
print json_str_1
print "\n"
print json_str_2
print "\n"
end
data1 = {
:a => 'xyz',
:b => 123,
:c => {:d => 'xxyyzz', :e => 456},
:f => [1,2,3,5,8,13]
}
output data1
data2 = Hash.new
data2["A"] = 'LMN'
data2["B"] = 789
data2["C"] = {"D" => 'XXYYZZ', "E" => 987}
data2["F"] = [1,2,3,5,7,11,13]
output data2
data3 = {}
data3["info"] = {
"count" => 3,
"query" => 'hoge'
}
data3a = Array.new
data3a[0] = {
"id" => 1,
"name" => "Alice"
}
data3a[1] = {
"id" => 2,
"name" => "Bob"
}
data3a[2] = {
"id" => 3,
"name" => "Carol"
}
data3["entry"] = data3a
output data3
JSON.generate はサイズが小さめの1行でのJSON形式の文字列に変換してくれる。
JSON.pretty_generate だと複数行に渡る読みやすいJSON形式の文字列に変換してくれる。
プログラムの実行結果がこれ。
$ ruby ./jsonsample.rb
{"f":[1,2,3,5,8,13],"a":"xyz","b":123,"c":{"d":"xxyyzz","e":456}}
{
"f": [
1,
2,
3,
5,
8,
13
],
"a": "xyz",
"b": 123,
"c": {
"d": "xxyyzz",
"e": 456
}
}
{"A":"LMN","B":789,"C":{"D":"XXYYZZ","E":987},"F":[1,2,3,5,7,11,13]}
{
"A": "LMN",
"B": 789,
"C": {
"D": "XXYYZZ",
"E": 987
},
"F": [
1,
2,
3,
5,
7,
11,
13
]
}
{"info":{"count":3,"query":"hoge"},"entry":[{"name":"Alice","id":1},{"name":"Bob","id":2},{"name":"Carol","id":3}]}
{
"info": {
"count": 3,
"query": "hoge"
},
"entry": [
{
"name": "Alice",
"id": 1
},
{
"name": "Bob",
"id": 2
},
{
"name": "Carol",
"id": 3
}
]
}
HashじゃないオブジェクトをHashのように使ってみたい。
オブジェクトの Hash への暗黙の変換が必要なときに内部で呼ばれます。デフォルトでは定義されていません。
説明のためここに記載してありますが、このメソッドは実際には Object クラスには定義されていません。必要に応じてサブクラスで定義すべきものです。
このメソッドを定義する条件は、
* ハッシュが使われるすべての場面で代置可能であるような、
* ハッシュそのものとみなせるようなもの
という厳しいものになっています。
instance method Object#to_hash (Ruby 1.8.6 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Objectクラス > to_hash)
そこで以下のような ToHashImplSmpl クラスを書いてみたけど、JSONライブラリでは to_hash を見てくれないみたい。
じゃあ、ToHashImplSmpl2 って Hash を継承したクラスに to_hash を実装してみたけど、これだとサブクラスの to_hash ではなくスーパークラスの Hash のほうの to_hash を使うみたい。
$ cat ./jsonsample2.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'json'
def output(json_data)
json_str_1 = JSON.generate(json_data)
json_str_2 = JSON.pretty_generate(json_data)
print json_str_1
print "\n"
print json_str_2
print "\n"
end
class ToHashImplSmpl
def to_hash
{ "a" => "A", "b" => 123}
end
end
class ToHashImplSmpl2 < Hash
def to_hash
{ "a" => "A", "b" => 123}
end
end
data1 = {
"c" => "xyz",
"ToHashImplSmpl.new" => ToHashImplSmpl.new,
"ToHashImplSmpl.new.to_hash" => ToHashImplSmpl.new.to_hash,
"ToHashImplSmpl2.new" => ToHashImplSmpl2.new,
"ToHashImplSmpl2.new.to_hash" => ToHashImplSmpl2.new.to_hash
}
output data1
# test for to_hash
p({"test" => "ToHashImplSmpl.new"}.merge(ToHashImplSmpl.new))
p({"test" => "ToHashImplSmpl.new.to_hash"}.merge(ToHashImplSmpl.new.to_hash))
p({"test" => "ToHashImplSmpl2.new"}.merge(ToHashImplSmpl2.new))
p({"test" => "ToHashImplSmpl2.new.to_hash"}.merge(ToHashImplSmpl2.new.to_hash))
実行結果は以下。撃沈。
$ ruby ./jsonsample2.rb
{"ToHashImplSmpl2.new.to_hash":{"a":"A","b":123},"ToHashImplSmpl.new.to_hash":{"a":"A","b":123},"c":"xyz","ToHashImplSmpl.new":"#<ToHashImplSmpl:0x100631630>","ToHashImplSmpl2.new":{}}
{
"ToHashImplSmpl2.new.to_hash": {
"a": "A",
"b": 123
},
"ToHashImplSmpl.new.to_hash": {
"a": "A",
"b": 123
},
"c": "xyz",
"ToHashImplSmpl.new": "#<ToHashImplSmpl:0x100631630>",
"ToHashImplSmpl2.new": {
}
}
{"a"=>"A", "b"=>123, "test"=>"ToHashImplSmpl.new"}
{"a"=>"A", "b"=>123, "test"=>"ToHashImplSmpl.new.to_hash"}
{"test"=>"ToHashImplSmpl2.new"}
{"a"=>"A", "b"=>123, "test"=>"ToHashImplSmpl2.new.to_hash"}
tags: Ruby JSON zurazure
Posted by NI-Lab. (@nilab)