JacksonでJSON文字列をScalaのcase objectにマッピングする
文字列をそのまま使うのではなく, 列挙型として扱いたい.
Enumeration
を使う方式なら,
公式にcom.fasterxml.jackson.module.scala.JsonScalaEnumeration
としてそのまま用意されています.
Enumerations · FasterXML/jackson-module-scala Wiki
でもEnumeration
は使いたくないですよね?
何が嫌かってValue
が型になるので型自体を参照するのに2段階ネストしないといけないのがイヤです.
あと後々class
にしたりメソッドを実装したりするかもしれませんし…
というわけでsealed trait
を使う方法を探しました.
簡単にColorで例えると以下のようになります.
import com.fasterxml.jackson.annotation._
sealed trait Color {
/** JSON文字列での表現 */
val stringView: String
@JsonValue def toJsonValue(): String = this.stringView
}
object Color {
@JsonCreator def fromJsonValue(stringView: String): Color = stringView match {
case Color.Red.stringView => Color.Red
case Color.Blue.stringView => Color.Blue
case _ => throw new IllegalArgumentException("Color: unsupport")
}
case object Red extends Color {
override val stringView = "red"
}
case object Blue extends Color {
override val stringView = "blue"
}
}
備忘録的なblog: [Jackson]Enumの値を読み書きする
が参考になりました. Javaのstaticメソッドはコンパニオンオブジェクトでもちゃんと模倣出来るようです.
ちょっとした注意点としてfromJsonValue
の返り値型を省略してはいけません.
推論されるからとりあえず開発中は…
とか思ってるとアノテーションしてるのにJacksonが認識してくれません.