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 ではアノテーションにも別名がつけられるらしい
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 beanscala> class Point(@bean var x: Int, @bean var y: Int)
defined class Pointほら、すっきり(?)