Jackson などの Java 製 JSON ライブラリで Scala の case class を自動的に json 変換するには

2018/02/28   #Scala  #Java  #Jackson 
このエントリーをはてなブックマークに追加

Spring Boot with Scala なアプリで、RestController でオブジェクトを return しても json がレスポンスされなかった(正確には {} と空 json がレスポンスされた)。Spring Boot が内部的に使用している Jackson は、オブジェクトを自動的によしなに json に変換してくれるハズである。
return した”オブジェクト”と言っているのは case class で、普通の class では大丈夫っぽかったので、case class 特有の何かをしないといけないのかなと。

調べた感じ、Scala の case class なんかは明示的に JavaBean を生成するように指定してあげる必要があるらしい。
具体的には case class のフィールドに @scala.beans.BeanProperty アノテーションをつけてあげる。

case class Emp(

  @BeanProperty
  name: String,

  @BeanProperty
  age: Int

)

@scala.beans.BeanProperty アノテーションをつけてあげたフィールドのみ json に出力された。

参考: java - Using Jackson to (De)-serialize a Scala Case Class - Stack Overflow


@BeanProperty は具体的に何をという話。

Scalaアノテーションメモ(Hishidama’s Scala annotation Memo)

JavaBeans形式のセッター・ゲッターメソッド(setZzz()・getZzz())が生成される。
@BooleanBeanPropertyだとゲッターがisZzz()になる。


とはいえ、 @BeanProperty をつけるのはダルい。
そんな人のために、Scala の case class を解釈してくれるようになる jackson-module-scala というライブラリがある。
FasterXML/jackson-module-scala: Add-on module for Jackson (http://wiki.fasterxml.com/JacksonHome) to support Scala-specific datatypes
これを使えば、いちいち @BeanProperty をつけなくてもシリアライズ/デシリアライズできるようになる。
結論的には jackson-module-scala 使えば何も考えなくていい 、ということになる。


番外編:
Scala ではアノテーションにも別名がつけられるらしい

Scala変態技法最速マスター - kmizuの日記

annotation alias
Java Beansとしても使えるようにしたいクラスを作りたいとき、Scalaでは@BeanPropertyアノテーションを使って、次のように記述できます:

scala> class Point(@BeanProperty var x: Int, @BeanProperty var y: Int)
defined class Point

しかし、BeanPropertyってなんか長ったらしくて嫌じゃないでしょーか?そんなとき、Scalaではアノテーションに別名をつけることができます。基本的に、普通の型の別名付けと同様、type宣言を使うだけなので簡単です。ためしに、@beanという別名を付けてみましょう:

scala> type bean = scala.reflect.BeanProperty
defined type alias bean

scala> class Point(@bean var x: Int, @bean var y: Int)
defined class Point

ほら、すっきり(?)