Play にいくつかのモデルがあります。JSON との間でシリアライズ/デシリアライズしたいアプリケーション。私はそのために別々の方法を持っていましたが、好ましい方法はFormats[T]
orの暗黙的Reads[T]
なインスタンスを与えることであることがわかりました。
import play.api.libs.json.{ JsValue, Reads }
case class Foo(bar: Int, ...)
object Foo {
implicit object FooReads extends Reads[Foo] {
def reads(json: JsValue): Foo = //whatever
}
}
ここで、モデルの JSON に正しいフィールドが含まれている場合がありますが、検証されません。この場合、デシリアライズできません。使用時json.as[Foo]
またはNone
使用時に例外が発生するはずjson.asOpt[Foo]
です。
検証されないフィールドを見つけたときに例外をスローすると、すべてが期待どおりに機能しているように見えます。しかし、私はどの例外をスローする必要があるかを見つけようとすることに注意を払い、ソースでJsValue
これを見つけました
def asOpt[T](implicit fjs: Reads[T]): Option[T] = fjs.reads(this).fold(
valid = v => Some(v),
invalid = _ => None
).filter {
case JsUndefined(_) => false
case _ => true
}
さて、これがどのように機能するのか理解できません。の暗黙的なインスタンスは、コンパニオン オブジェクトで自分自身によって提供されるため、例外を返すか例外をスローするかがfjs
わかります。fjs.reads(this)
Foo
これはどこfold
から来たのですか?それは確かに のメソッドではありませんFoo
。暗黙の変換ができると思いますがAny
、メソッドを使用して何かに変換する必要がfold
あるため、あまり興味深いものではありません。さらに悪いことにfjs.reads(this)
、例外がスローされた場合、それをキャッチするものは何もありません!
では、のインスタンスで JSON の無効な入力をどのように処理すればよい
Reads[T]
でしょうか? そして、上記のメカニズムは実際にどのように機能するのでしょうか?