• 作成:

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が認識してくれません.