2012-10-05 2 views
1

Play! JSON에서 serialize/deserialize하고 싶습니다. 이 모델이 올바른 필드를 가지고 발생할 수 있습니다, 그에 대해 별도의 방법을 가지고하는 데 사용하지만 지금Play 프레임 워크에서 읽기, 쓰기 및 형식 사용

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 
    } 
} 

처럼, 선호하는 방법은 Formats[T] 또는 Reads[T]의 암시 적 인스턴스를 제공하는 것을 보았다 JSON,하지만 유효성을 검사하지 않습니다. 이 경우에는 역 직렬화 할 수 없습니다. json.asOpt[Foo]을 사용하는 경우 json.as[Foo] 또는 None을 사용할 때 예외가 발생합니다.

유효성을 검사하지 않는 필드를 발견했을 때 예외가 발생하면 모든 것이 예상대로 작동하는 것 같습니다. 하지만 내가 던져해야하는지 예외 알아 내려고의 배려를 가지고 가고, 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을 반환하거나 예외를 throw합니다.

여기가 어디입니까? fold 확실히 Foo의 방법은 아닙니다. 하나는 암시 적 변환을 할 수 있다고 생각하지만 Any에서 fold 메쏘드가있는 무언가에 있어야하므로 많은 관심이 없습니다. 심지어 악화, fjs.reads(this) 예외를 throw하는 경우, 그것을 잡을 아무것도 없습니다!

그렇다면 Reads[T] 인스턴스에서 JSON의 잘못된 입력을 어떻게 처리해야합니까? 그리고 위의 메커니즘은 실제로 어떻게 작동합니까?

답변

1

플레이 커널 2.0.x에서 JsonValue.scala에서 상대 : 사실 코드가 Catch[T] 반환 scala.util.control.Exception.catching[T](exceptions: Class[_]*): Catch[T]을 사용

def asOpt[T](implicit fjs: Reads[T]): Option[T] = catching(classOf[RuntimeException]).opt(fjs.reads(this)).filter { 
    case JsUndefined(_) => false 
    case _ => true 
} 

. 그런 다음 opt (...)를 호출합니다. 예외가 Throw되면 T 대신에 None을 반환합니다.

따라서 비 직렬화 오류가 발생하면 안전하게 예외를 throw 할 수 있습니다.

+0

그건 절대적으로 의미가 있습니다. 이제 나는 어제 브라우징하는 버전을 '잡기'하지 않고 다른 정의를 찾았을 때 궁금해졌습니다. : -? 나도 링크를 포함하지 않았다. ... – Andrea

+0

좋아, 찾았 어 https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/libs /json/JsValue.scala 그것은 master에있는 버전으로 아마도 Play 2.1의 코드베이스입니다. 나는 더 잘 봐야했다. .. – Andrea

관련 문제