Play Framework を始めたばかりの方向けに、サンプルを進めるうえで困ったところを共有する目的で書いています。
Play Framework 2.8.x にて、JSON に case object を使うときのメモです。
以下、目次
前提
こんな感じの case object を含んだ case class を、
sealed trait Color case object Red extends Color case object Yellow extends Color case object Green extends Color case class Origami(color: Color)
こんな感じの JSON でやりとりしたい
{ "origami" : { "color" : "Red" } }
方針
- case object が増えたりしたときに、変更箇所が少ない or コンパイルエラーで変更すべき箇所を教えてくれる
- case object のパターンマッチは残したい
結果
build.sbt
libraryDependencies += "com.beachape" %% "enumeratum" % "1.7.0",
こんな感じで、
import enumeratum.EnumEntry import enumeratum.Enum sealed trait Color extends EnumEntry object Color extends Enum[Color] { case object Red extends Color case object Yellow extends Color case object Green extends Color lazy val values: IndexedSeq[Color] = findValues } import play.api.libs.json._ implicit val colorWrites = new Writes[Color] { override def writes(color: Color): JsValue = Json.toJson(color.toString) } implicit val colorReads = new Reads[Color] { override def reads(json: JsValue): JsResult[Color] = json.asOpt[String].flatMap(Color.withNameOption(_)) match { case Some(color) => JsSuccess(color) case None => JsError("cannot parse to Color.") } } case class Origami(color: Color) implicit val origamiFormat = Json.format[Origami]
こうなります。
scala> :paste val json: JsValue = Json.obj( "origami" -> Json.obj( "color" -> "Red" ) ) val json: play.api.libs.json.JsValue = {"origami":{"color":"Red"}} scala> (json \ "origami").validate[Origami](origamiFormat).get val res0: Origami = Origami(Red)
参考にしたところ
- JSON basics
- JSON automated mapping
- 【Scala】play-jsonのReads/Writes頻出パターン5選
- Scalaで実用的な列挙型(enum)を定義する ※enumeratum使用
以上でした。