Avroとsbtを使ってentityクラスを自動生成する(Java, Scala)


こんにちは、@s_tsukaです。

Apache Avroはデータのシリアライズシステムですが、今回はこれをsbtで利用する話です。

Aache Avro

Apache Avroのフォーマットでentity(ようするにデータ用のクラス)のスキーマを定義し、そのスキーマファイルからentityのクラスを自動生成する、というものです。

sbt/sbt-avroを使ってJavaクラスを自動生成

https://github.com/sbt/sbt-avro

※Scalaユーザの方は使わないほうが良いと思います。

最近のJava業界ではどのビルドツールが流行ってるんでしょうか。やはりMaven…?

Mavenの方は調べていないのですが、sbtにはこのプラグインがありました。

使い方は簡単で、基本READMEに従えばOKです

  1. plugins.sbtにsbt-avroを追加
  2. build.sbtにavroSettingsを読み込むコードを追加
  3. src/main/avroフォルダにavroフォーマットのスキーマファイルを追加

この状態でsbt compileすれば自動でsbt-avroのコードgenerateが始まって、最終的にtargetフォルダ配下のsrc_managedやclassesフォルダ配下に.javaファイルや.classファイルができます。

src/main/avroフォルダに置くファイルはuser.avscとかの名称で

{
  "namespace": "avro.entity",
  "type": "record",
  "name": "User",
  "fields": [
    {"name": "name", "type": "string"},
    {"name": "favoriteNumber",  "type": ["int", "null"]},
    {"name": "favoriteColor", "type": ["string", "null"]}
  ]
}

こんな感じで置いておけば大丈夫です。

src/main/avroのパスが気に入らなかったり、stringがCharSequenceに展開されるのが気に食わない場合はbuild.sbtにこんな感じで追加設定を入れればOKです。

(stringType in avroConfig) := "String"

(sourceDirectory in avroConfig) := file("src/main/resources")

残念ながら生成されるのはScalaコードではないので、Scalaユーザは以下のものを使ったほうが良さそうです。

julianpeeters/sbt-avrohuggerを使ってScalaコードを自動生成

https://github.com/julianpeeters/sbt-avrohugger

こちらはScalaコードを生成してくれます。

こちらも使い方は先ほどとほぼ同じです。READMEを見ればわかるかと思います。

これを使うと以下のようにScalaコードが生成されます。

/** MACHINE-GENERATED FROM AVRO SCHEMA. DO NOT EDIT DIRECTLY */
package avro.entity

case class User(name: String, favoriteNumber: Option[Int], favoriteColor: Option[String])

ちゃんとOptionになってます!

とはいえ、ファイルの内容がこれしかないので、AvroのAPIに沿っているクラスなのかというと怪しい気がします。このクラスから生成したオブジェクトをAvro形式でシリアライズするときはまた別のライブラリを使わないといけない気がします。そのへんどうなんでしょう・・。

以上です。

補足

コメント欄にもありますが、julianpeeters/sbt-avrohugger がわざわざ教えてくれました、ありがとう!

上記で「AvroのAPIに沿っているクラスなのかというと怪しい気がします。」と言っていますが、これはsbtavrohubber.SbtAvrohugger.avroSettingsを使っているからそうなるようですね。Avroに準拠したcase classを作りたい場合は、sbtavrohugger.SbtAvrohugger.specificAvroSettingsの方を使えば良いようです。解決!

以上です