saba1024のブログ

どうでも良い思いついた事とかプログラミング関係のメモとか書いていきます。

GroovyでJSONを生成する(JsonBuilder)

GroovyのコードとしてJSONを生成する

特に難しい内容ではないのですが、自分で使う時に毎回ググっているので備忘録として纏めます。
JsonBuilderというGroovy標準のクラスを利用することで簡単にJSONを生成することが出来ます。

import groovy.json.*
def json = new JsonBuilder()
json(
    name: 'koji',
    age: 32,
    hobbies: [[id: '1', name:'hobby1'], [id: 2, name: 'hobby2']],
    address: [country: 'japan', city: 'tokyo']
)
println json.toPrettyString()

実行結果は以下の様になります。

{
    "name": "koji",
    "age": 32,
    "hobbies": [
        {
            "id": "1",
            "name": "hobby1"
        },
        {
            "id": 2,
            "name": "hobby2"
        }
    ],
    "address": {
        "country": "japan",
        "city": "tokyo"
    }
}

ぱっと見で分かるシンプルな例ですが、
nameageはそれぞれ普通の値です。
hobbiesは、オブジェクトを格納する配列です。
addressは、オブジェクトを格納するオブジェクトです。
また、nameageのように、Groovyが自動的に型を判断してダブルクオーテーションで囲んだりしてくれています。非常に楽ちんです。

公式ドキュメントには、JsonBuilderに対してjson{...}というサンプルが用意されていますが、それだと上記のようなhobbies配列にオブジェクトを渡すことが出来ません。(出来るとは思うのですが自分はその方法を知りません。。。)
そこで、JsonBuilderをjson(...)という形で呼び出すようにすれば、JSONの値はすべてMapで記述することが出来ます。

もう少し詳細

jsonに続いて書く内容は、すべてcallメソッドへ渡されて実行されます。
callメソッドは渡される型によっていくつかオーバロードされています。

json {...}は、JsonBuilder#call(Closure)が呼ばれ、json(...)JsonBuilder#call(Map)が呼ばれている形です。
少し混乱しそうですが、Groovyは引数としてに渡すMapの場合、最初の[ ]は省略できます。
そして、引数があるメソッドを実行する際には、引数の( )を省略できます。

まとめると、 json(...)は、json.call([:])を実行していて、json{}json.call({クロージャ})を実行している、という事になります。

慣れるまでは、なんだかよく分からん、という状態になりそうですが、基本的にはJSONにしたい値をすべてMapで表現しておいて、それをJsonBuilderに渡してあげれば問題ないと思います。

参考:
JsonBuilder

追記

callにクロージャを渡して、配列も定義できる方法を教えて頂きました。

教えて頂いたリンク先のコードは以下のようになっています。

import groovy.json.*
def json = new JsonBuilder()
json {
    name 'koji'
    age 32
    hobbies([id: '1', name:'hobby1'], [id: 2, name: 'hobby2'])
    address([country: 'japan', city: 'tokyo'])
}

println json.toPrettyString()

hobbiesのような配列のものも( )で囲めばイケるようです。