log

日記です

play.api.libs.json で複数の型を受け取る

多分もっと良いやり方ある。。。

例えば{id: "1", value: 1} とかあるとvalueはIntじゃないと受け取れないと。1だったり"1"が混合していると詰む。全部Stringにしたい。どうしたら良いか?くっそハマったのでメモを残しておきます。

これが変換ルールです。

readNullable(
    Reads.of[String] or 
      Reads.of[Int].map(_.toString) or
      Reads.of[Double].map(_.toString))

sample code

case class Hoge(
  id: String,
  nanika: Option[String],
  value: Option[String]
)
object Hoge {
  implicit val rds: Reads[Option[String]] = (__ \ "value").readNullable(
    Reads.of[String] or 
      Reads.of[Int].map(_.toString) or
      Reads.of[Double].map(_.toString))
  
  implicit val wrs: OWrites[Option[String]] = (__ \ "value").writeNullable[String]
  implicit val formt: Format[Hoge] = (
    (__ \ 'id).format[String] ~
      (__ \ 'nanika).formatNullable[String] ~
      (__).format(rds)(wrs)
    )(Hoge(_,_,_), unlift(Hoge.unapply))
}

ググってギリギリ見つけたのがofを使う方法で、ofとか解決できないんだけどどこにあるのと思いコードを見てみると、play.api.libs.json.Readsにplay.api.libs.json.ConstraintFormatがミックスインされて実装されていました。。 import play.api.libs.json.Reads._ したほうがReads.は省略できていいかもです。