速水 康晴
 速水 康晴(はやみ やすはる)
 新潟県新潟市西区在住
 ウイングアーク1st株式会社 新潟オフィス
◦ プログラマ(アーキテクト):Java/Flex/ActionScript
 JGGUG(日本Grails/Groovyユーザーグループ)
◦ サポート・スタッフ
 E-mail:toby55kij@gmail.com
 Twitter:toby55kij
22015-6-26
 GroovyでJSONを扱う
 Groovy2.4での変更点
 JsonSlurperの話
◦ シリアライズについて
◦ Chopについて
◦ その他
2015-6-26 3
 「13日の金曜日」が年3回
◦ 2/13
◦ 3/13
◦ 11/13
 「JSON日の金曜日」も年3回?
◦ 新潟市で行われているJSON勉強会(時々懇親会だけ)
◦ 今年は2回開催(1回は懇親会だけ)
2015-6-26 4
 バージョン1.8からサポート
◦ groovy.json.JsonBuilder
 JSON作成用Builder
◦ groovy.json.StreamingJsonBuilder
 Writerに書きこむJsonBuilder:1.8.1から
◦ groovy.json.JsonOutput
 JSONとしてオブジェクトを文字列に出力
◦ groovy.json.JsonSlurper
 JSON文字列・ファイルの読み込み
2015-6-26 5
 JsonBuilder:JSON文字列をDSLで構築
◦ Writerに直接書き込む:StreamingJsonBuilder
 例:
def json = new groovy.json.JsonBuilder()
json {
person {
firstName 'Yasuharu'
lastName 'Hayami'
}
age 42
}
println json.toString()
2015-6-26 6
 JsonOutput:オブジェクトを文字列に出力
◦ prettyPrint(String)で文字列を整形
 例:
def obj = [person:
[firstName: 'Yasuharu', lastName: 'Hayami'],
age: 42]
File file = new File('output.json')
use(groovy.json.JsonOutput) {
file.text = obj.toJson().prettyPrint()
}
2015-6-26 7
 JsonSlurper:JSON文字列を読み込む
◦ 結果はJavaのListやMapに
 例:
def slurper = new groovy.json.JsonSlurper()
def data = slurper.parseText '''{
"person": {
"firstName": "Yasuharu",
"lastName": "Hayami"
},
"age": 42
}'''
println "${groovy.json.JsonOutput.toJson data}"
2015-6-26 8
 JsonBuilder/StreamingJsonBuilderの再実装
◦ Javaで書き換え→JSON実装はすべてJavaに
2015-6-26 9
 JsonSlurperの結果はシリアライズ可能ではない
◦ 使用クラスにjava.io.Serializableが実装されていない
◦ 解析の種類によって使用クラスは異なる
 JsonSlurperClassicの結果はシリアライズ可能
2015-6-26 10
 typeで選択:値はJsonParserType
◦ CHARACTER_SOURCE:Readerで読みながら
 大きいファイル(2MB以上)で使用
◦ CHAR_BUFFER:一旦文字列バッファ(char配列)に読み込む
 デフォルト、数字・日付を「きちんと」解析したい場合に使用
◦ LAX:値を文字列バッファへのポインタで持つ
 コメントを含む場合に使用
 長期的に値を持つ場合'Chop'か'Lazy Chop'を指定しておく
◦ INDEX_OVERLAY:値を文字列バッファへのポインタで持つ
 最速、2MB以下での使用がおすすめ
 長期的に値を持つ場合'Chop'か'Lazy Chop'を指定しておく
2015-6-26 11
 Readerで固定char配列に読みながら解析
 groovy.json.internal.JsonParserUsingCharacterSource
◦ 値は各クラス
◦ 配列はArrayList
◦ オブジェクトはgroovy.json.internal.LazyMap
 Serializableが実装されていない!
2015-6-26 12
 一旦文字列バッファ(char配列)に読み込んで解析
 groovy.json.internal.JsonParserCharArray
◦ 値は各クラス
◦ 配列はArrayList
◦ オブジェクトはgroovy.json.internal.LazyMap
 Serializableが実装されていない!
2015-6-26 13
 一旦文字列バッファ(char配列)に読み込んで解析
 LAX:groovy.json.internal.JsonParserLax
 INDEX_OVERLAY:groovy.json.internal.JsonFastParser
◦ 値はValueインターフェースの実装
 char配列,開始位置,終了位置を持つ
 数値:groovy.json.internal.NumberValue
 文字列:groovy.json.internal.CharSequenceValue
 その他:groovy.json.internal.ValueContainer
 toValue()で格納した値を返す(true/false/nullは直接返す)
 配列はgroovy.json.internal.ValueListで格納
 オブジェクトはgroovy.json.internal.LazyValueMapで格納
 Key-Valueは一旦groovy.json.internal.MapItemValueで保管
 最初のget()でMapに変換
 Serializableが実装されていない!
2015-6-26 14
 Chopとは(LAX,INDEX_OVERLAY)
◦ 対象の部分を抜き出して新たな文字列バッファ作成
 開始位置は0
 終了位置はchar配列の長さ
2015-6-26 15
 JsonSlurper#setChop()
◦ インスタンスを作成する際にChopするか
◦ デフォルトはfalse
 JsonSlurper#setLazyChop()
◦ 配列・オブジェクトから値を取得する際にChopするか
◦ デフォルトはtrue
◦ setChop(true)だと無意味
2015-6-26 16
 日付文字列の判定(LAX,INDEX_OVERLAY)
◦ Value#toValue()で日付文字列の場合Date型で返す
◦ JsonSlurper#setCheckDates()で指定
2015-6-26 17

JsonSlurperの話