No Programming, No Life

新しいNPNLです。http://d.hatena.ne.jp/fumokmm/ から引っ越してきました。

GroovyでJSONを使おう(その2)

このシリーズの一覧はこちら

はじめに

前回は自分でクラスを書いて対応していましたが、Groovyのv1.8からJSONは組み込みでサポートされるようになりました。

f:id:fumokmm:20110226213619p:image

Groovy本家より

この機能は既にGroovyにあるXMLの生成や読み込みをサポートするMarkupBuilder, XmlSlurper, XmlParserのJSON版と捉えると理解が早いです。
ということで、簡単なサンプルをご紹介します。
(動作確認: Groovy Version: 1.8.0-rc-1 JVM: 1.6.0_22)

準備

用意したjsonはこんな内容です。

json.txt
[
  ["aaa", "bbb", "ccc"],
  {
    "key1" : "value1",
    "key2" : "value2",
    "key3" : "value3",
    "key4" : ""
  },
  ["ddd", "eee", "fff"]
]

読み込み

まずは読み込み。groovy.json.JsonSlurperというクラスを使うと実現できます。

jsonTestRead.groovy
import groovy.json.*

def slurper = new JsonSlurper()
def text = new File('json.txt').text
def root = slurper.parseText(text)

assert root == [
  ['aaa', 'bbb', 'ccc'],
  [key1: 'value1', key2: 'value2', key3: 'value3', key4: ''],
  ['ddd', 'eee', 'fff']
]

JsonSlurperを使ってparseした結果はjava.util.ArrayListjava.util.HashMapで返ってくるようです。HashMapで返ってくるから、サンプルのkey1〜key4の部分は順番が保証されないことに注意する必要がありそうですね。

assert root instanceof ArrayList
assert root[0] instanceof ArrayList
assert root[1] instanceof HashMap
assert root[2] instanceof ArrayList

値へのアクセスは通常のGroovyからListやMapにアクセスする方法が利用できます。

assert root[1].key3 == 'value3'
assert root.last().last() == 'fff'

書き込み

では次に書き込み。groovy.json.JsonBuilderというクラスを使うと実現できます。
例として読み込みで使ったjsonと同じものをJsonBuilderで作ってみます。

jsonTestWrite.groovy
import groovy.json.*

def json = new JsonBuilder()
json (
  ['aaa', 'bbb', 'ccc'],
  [
    key1: 'value1',
    key2: 'value2',
    key3: 'value3',
    key4: ''
  ],
  ['ddd', 'eee', 'fff']
)

new File('json2.txt').text = json.toString()
結果
$ groovy jsonTestWrite.groovy
$ cat json2.txt
[["aaa","bbb","ccc"],{"key1":"value1","key2":"value2","key3":"value3","key4":""},["ddd","eee","fff"]]

うまいことJSONが作成できました。改行などがないので可読性は低いですが、意味的には同じものができています。

このサンプルでは単純にGroovyのListやMapを組み合わせてJSONを作成したのですが、JsonBuilderのDSLsの実力はまだまだこんなものではありません。

オブジェクトとリストの複合を作ったり
def json = new JsonBuilder()
json 1, 2, [k: true], "a", "b", [3, "c"]

assert json.toString() == '[1,2,{"k":true},"a","b",[3,"c"]]'
シンプルなobject形式を作ったり
def json = new JsonBuilder()
json {
  a 1
  b true
  c null
}

assert json.toString() == '{"a":1,"b":true,"c":null}'
ネストしたオブジェクトを作ったり
def json = new JsonBuilder()
json {
  a {
    b {
      c 1
    }
  }
}

assert json.toString() == '{"a":{"b":{"c":1}}}'

と色々できるようです。「a 1」のような記述でオブジェクトが作れるあたりがDSLsな匂いがしますね。
興味が湧いてきた方は以下のもっと詳しい使い方を参照してみて下さい。

もっと詳しい使い方

GEP 7 - JSON Support - Groovy JSR - Codehaus
JsonSlurperのUnitTest
JsonBuilderTestのUnitTest
ここにあるUnitTestコードが分かりやすいと思います。

まとめ

Webアプリケーションとの連携ではJSONを自由に扱えることは必須となってきています。以前でも、ライブラリを利用すればJSONは利用できていましたが、組み込みサポートされたことにより今後はもっと気軽にJSONをデータ形式として扱えるようになりました。
どんどんJSONを使って行きましょう!