播放2.3隐式json转换导致空指针异常 [英] Play 2.3 implicit json conversion causes null pointer exception
问题描述
我正在尝试将json解析为我的案例类DealFormMap
I'm trying to parse json into my case class DealFormMap
case class DealFormMap(limit: Option[Int], filter: Option[DealFormFilterMap])
case class DealFormFilterMap(date: Option[String], code: Option[String])
implicit val dealFormMapReads: Reads[DealFormMap] = (
(JsPath \ "limit").readNullable[Int] and
(JsPath \ "filter").readNullable[DealFormFilterMap]
)(DealFormMap)
implicit val dealFormFilterMapReads: Reads[DealFormFilterMap] = (
(JsPath \ "date").readNullable[String] and
(JsPath \ "code").readNullable[String]
)(DealFormFilterMap)
有问题的JSON和解析尝试
JSON in question and parsing attempt
val str = """{"limit":10,"filter":{"date":"2014-10-27"}}"""
val frm = Json.parse(str).as[DealFormMap]
导致我似乎无法破解的神秘错误堆栈
causes a cryptic error stack that I just can't seem to crack
play.api.Application$$anon$1: Execution exception[[NullPointerException: null]]
at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.5.jar:2.3.5]
at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.5.jar:2.3.5]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:205) [play_2.11-2.3.5.jar:2.3.5]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:202) [play_2.11-2.3.5.jar:2.3.5]
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.2.jar:na]
Caused by: java.lang.NullPointerException: null
at play.api.libs.json.PathReads$$anonfun$nullable$1$$anonfun$apply$7$$anonfun$apply$9.apply(JsConstraints.scala:65) ~[play-json_2.11-2.3.5.jar:2.3.5]
at play.api.libs.json.PathReads$$anonfun$nullable$1$$anonfun$apply$7$$anonfun$apply$9.apply(JsConstraints.scala:63) ~[play-json_2.11-2.3.5.jar:2.3.5]
at play.api.libs.json.JsResult$class.fold(JsResult.scala:76) ~[play-json_2.11-2.3.5.jar:2.3.5]
at play.api.libs.json.JsSuccess.fold(JsResult.scala:9) ~[play-json_2.11-2.3.5.jar:2.3.5]
at play.api.libs.json.PathReads$$anonfun$nullable$1$$anonfun$apply$7.apply(JsConstraints.scala:61) ~[play-json_2.11-2.3.5.jar:2.3.5]
我这里的想法不多了,可能是什么问题?
I'm running out of ideas here, what could be the problem?
推荐答案
问题是初始化顺序. dealFormMapReads
依赖于隐式dealFormFilterMapReads
,直到此后才定义.它将进行编译,因为即使未初始化隐式变量,也已找到它,因此dealFormMapReads
被读取为null
,最终导致NPE.
The problem is the initialization order. dealFormMapReads
depends on the implicit dealFormFilterMapReads
, which isn't defined until after. It will compile because the implicit is found, even though it hasn't been initialized, so dealFormMapReads
is read as null
, which eventually causes the NPE.
延迟加载将解决此问题:
Lazily loading will fix it:
implicit val dealFormMapReads: Reads[DealFormMap] = (
(JsPath \ "limit").readNullable[Int] and
(JsPath \ "filter").lazyReadNullable[DealFormFilterMap](dealFormFilterMapReads)
)(DealFormMap)
或者您可以交换定义Reads
的顺序.
Or you could just swap the order in which the Reads
are defined.
此处抛出的NPE与以下示例类似:
The NPE thrown here is similar to this example:
case class A(i: Int)
object Test {
val test = a.toString
val a = A(1)
}
// Compiles up to here
Test.test // throws NPE, because `a` was not initialized before `test`
这篇关于播放2.3隐式json转换导致空指针异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!