手元にあるcsvファイルをElasticsearchにbulkAPIで投入したかったので、JSONに変換するgroovyスクリプトを書きました。
意外にも新しい発見もあったのでメモ代わりに残しておきます。
inputファイル
見出し行がついたCSVファイル(UTF-8)を想定。
event_date_time,name
2015/09/01 01:02:03,田中
2015/09/02 04:05:06,山田
ソース
import groovy.json.JsonBuilder
import groovy.json.StringEscapeUtils
new File("output.json").withWriter("UTF-8") { writer ->
new File("input.csv").eachLine("UTF-8", 0){ String line, int number ->
if(number == 0) return
def data = line.split(",")
def json = new JsonBuilder()
json (
"index" : [
"_index": "index_name",
"_type" : "type_name",
"_id" : number
],
"event_date_time" : data[0],
"name" : data[1]
)
writer.write(StringEscapeUtils.unescapeJavaScript(json.toString()) + "\n")
}
}
勉強になったこと(1) firstLineの意味
java.io.File#eachLine(String charset, int firstLine, Closure c)
のfirstLineですが、2と指定すると1行目を無視して2行目から読み込んでくれるのかと思っていました。
そのため、以下のようなコードを書き、なんで全部出力されるんだろうと??な状態でした。
new File("input.csv").eachLine(2){ String line ->
・・・
}
よくよくドキュメントを読むと普通に書いてありました。
実はclosureに渡す行番号の初期値とのこと。
Parameters:
firstLine - the line number value used for the first line (default is 1, set to 0 to start counting from 0)
closure - a closure (arg 1 is line, optional arg 2 is line number)
ファイル操作ではeachWithIndexがないのかと思っていたら、その機能相当のものがeachLineでできたんですね。知らなかった。
勉強になったこと(2) JsonBuilderで日本語出力する
groovy.json.JsonBuilder#toString()
では日本語はエスケープされた状態で出力されるようです。
エスケープされた文字を元に戻すためには、groovy.json.StringEscapeUtils#unescapeJavaScript(String str)
を使ってやればいいようです
簡単なスクリプトですがやはり自分で手を動かすと理解も深まります。