JSONの中にJSONが突っ込まれてるやつを綺麗にするやつのGo版
jl
Perlでその昔、App::jl というコマンドラインツールを書きました。これは jl
(じぇい、える)というコマンドで、JSONの中にJSONが突っ込まれているログを綺麗にひとつのJSONに整形して表示してくれるツールです。よく「ああ、JSONをprettifyするやつね、あるある」という完全な誤解を受けるのですが、割とそんなに甘いやつじゃなくて、JSONの中にエスケープされたJSONが入ってるやつを頑張って目parseしてるみなさまに優しいやつです。jl
を使えば、今日からJSONの中にJSONがあってエスケープされてて面倒いやつが簡単に jq
で処理できるようになります。魔法のコマンドです。
というコマンドが Perl にあったのですが、このたび Go で書きなおしてバイナリポン!もしくは homebrew ですぐインストールして使えるようにしました。
Mac の homebrew なら以下のようにインストールできます
brew tap bayashi/go-jl
brew install bayashi/go-jl/go-jl
バイナリからのインストールはこちらからどうぞ。解凍して出てきた jl
をパスの通ったところに置くだけで使えます。
https://github.com/bayashi/go-jl
実例
以下の JSON の message キーの値に入っている文字列は、エスケープされたJSONなので、そのままでは jq で要素を指定したりできませんが、jl
に渡せばシュッとひとつの JSON になります。
$ echo '{"message": "{\"level\":\"info\",\"ts\":1557004280.5372975,\"caller\":\"zap/server_interceptors.go:40\",\"msg\":\"finished unary call with code OK\",\"grpc.start_time\":\"2019-05-04T21:11:20Z\",\"system\":\"grpc\",\"span.kind\":\"server\",\"grpc.service\":\"FooService\",\"grpc.method\":\"GetBar\",\"grpc.code\":\"OK\",\"grpc.time_ms\":248.45199584960938}\n","namespace": "foo-service","podName": "foo-86495899d8-m2vfl","containerName": "foo-service"}' | jl -p
{
"containerName": "foo-service",
"message": {
"caller": "zap/server_interceptors.go:40",
"grpc.code": "OK",
"grpc.method": "GetBar",
"grpc.service": "FooService",
"grpc.start_time": "2019-05-04T21:11:20Z",
"grpc.time_ms": 248.45199584960938,
"level": "info",
"msg": "finished unary call with code OK",
"span.kind": "server",
"system": "grpc",
"ts": 1557004280.5372975
},
"namespace": "foo-service",
"podName": "foo-86495899d8-m2vfl"
}
stern を使って JSON で吐き出したときによくあるやつがきれいに見えますね!
ちなみに -p
つけなければインデントしない一行 JSON で出力されます。
Go実装の感想
JSON を再帰的に Unmarshal するのに、いったん別のデータ構造に変換してから、Golang の表現に戻して、最終的に JSON に Marshal するということをやっています。行きも帰りも再帰だらけで疲れました。Perl で書いたときの10倍くらい大変でしたが、学びも多かったので良しとしましょう。リファクタリングはまだこれからです。
テストはそこそこあるので十分動くと思いますが、実践的なログではまだあまり試してないので不具合あったら教えてください。
Perl版にはいろいろと細かい機能がついていて、Go版とは機能差分も多いので、必要そうなのは最低限取り込もうかなと思っています。とはいえ、Perl版は勢いでもりもりさせすぎているので、Go版は絞っていこうかなと思っています。
ではでは。