播放2.3隐式json转换导致空指针异常 [英] Play 2.3 implicit json conversion causes null pointer exception

查看:99
本文介绍了播放2.3隐式json转换导致空指针异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆