我有一个JSON文档,其中一些值可以为null。在json4s中使用for表达式,我怎么能产生None而不是什么?
当FormattedID
或PlanEstimate
字段的值为null
时,以下内容将无法生成。
val j: json4s.JValue = ...
for {
JObject(list) <- j
JField("FormattedID", JString(id)) <- list
JField("PlanEstimate", JDouble(points)) <- list
} yield (id, points)
例如:
import org.json4s._
import org.json4s.jackson.JsonMethods._
scala> parse("""{
| "FormattedID" : "the id",
| "PlanEstimate" : null
| }""")
res1: org.json4s.JValue = JObject(List((FormattedID,JString(the id)),
(PlanEstimate,JNull)))
scala> for {
| JObject(thing) <- res1
| JField("FormattedID", JString(id)) <- thing
| } yield id
res2: List[String] = List(the id)
scala> for {
| JObject(thing) <- res1
| JField("PlanEstimate", JDouble(points)) <- thing
| } yield points
res3: List[Double] = List()
// Ideally res3 should be List[Option[Double]] = List(None)
答案 0 :(得分:3)
scala> object OptExtractors {
|
| // Define a custom extractor for using in for-comprehension.
| // It returns Some[Option[Double]], instead of Option[Double].
| object JDoubleOpt {
| def unapply(e: Any) = e match {
| case d: JDouble => Some(JDouble.unapply(d))
| case _ => Some(None)
| }
| }
| }
defined object OptExtractors
scala>
scala> val j = parse("""{
| "FormattedID" : "the id",
| "PlanEstimate" : null
| }""")
j: org.json4s.JValue = JObject(List((FormattedID,JString(the id)), (PlanEstimate,JNull)))
scala>
scala> import OptExtractors._
import OptExtractors._
scala>
scala> for {
| JObject(list) <- j
| JField("FormattedID", JString(id)) <- list
| JField("PlanEstimate", JDoubleOpt(points)) <- list
| } yield (id, points)
res1: List[(String, Option[Double])] = List((the id,None))
答案 1 :(得分:1)
任何值都可以是可选的。字段和值完全删除时 它没有价值。
阶&GT; val json =(“name” - &gt;“joe”)〜(“age” - &gt;(None:Option [Int]))
阶&GT;紧凑(渲染(JSON))
res4:String = {“name”:“joe”}
解释为什么你的理解不会产生任何结果。
当然,null
值会在内部映射到None
。
答案 2 :(得分:0)
最后一个命令应如下所示:
for {
JObject(thing) <- res1
} yield thing.collectFirst{case JField("PlanEstimate", JDouble(points)) => points}
或者喜欢
for {
JObject(thing) <- res1
points = thing.collectFirst{case JField("PlanEstimate", JDouble(p)) => p}
} yield points
答案 3 :(得分:0)
这个怎么样?
for {
JObject(thing) <- res1
x = thing.find(_._1 == "PlanEstimate").flatMap(_._2.toOption.map(_.values))
} yield x