Scala:使用asOpt [T]解析json返回None虽然我有价值

时间:2015-04-26 14:15:23

标签: json scala

我试图使用asOpt [T]提取值,因为我可能没有密钥。虽然我的字符串中有值,但我得到了回报。

val jsonString = {"data": {"operation":"+", "value":"1"},"right": {"data":{"operation":"-", "value":"2"}},"left":{"data":{"operation":"-", "value":"4"}}}
buildFromJson(jsonString)

代码:

import play.api.libs.json.Json
...
def buildFromJson(jsonString: String) : TreeNode = {
    val nodeData = json.\("data")
    val nodeValue = nodeData.\("operation").as[String] //This works

    println("left= " + json.\("left").asOpt[String]) //output= None
    println("left= " + json.\("left").as[String]) // throws exception
    println("left= " + json.\("left").toString) //output= {"data":{"operation":"-", "value":"4"}}

解析可能不存在的JSON密钥的最佳方法是什么?正如我所读到的那样,它已经开始了,但它并没有起作用。

更新 - 我如何克服这个问题:

1)首先m-z是对的,它确实是对象,不能作为String返回。

2)我无法找到一种提取可能不存在的字段的好方法(就像刚开始时我只在正确的子节点存在时才添加'右边的json)。现在我添加到json'右边'如果字段不存在,则为空值。

1 个答案:

答案 0 :(得分:0)

你可以检查一个值是否为None,但这通常是一个坏主意。它导致模糊代码与大量的模式匹配/错误处理代码/ if / etc ...好消息是OptionJsResult都是monad!你可以使用你喜欢的那个,但我更喜欢JsResult,因为它会给出错误消息,而Option只是给你None(知道在哪里寻找错误总是比不得不更好测试每一行)。

假设您有一个alegraic数据类型TreeNode:

abstract class TreeNode
case class Leaf(operation : String, value : String) extends TreeNode
case class Node(l : Leaf, left : TreeNode, right : TreeNode) extends TreeNode

解析功能可以是:

def buildTreeNode(json: JsValue) : JsResult[TreeNode] =
    for {operation <- (json \ "data" \ "operation").validate[String]
         value     <- (json \ "data" \ "value").validate[String]
         leaf      = Leaf(operation, value)
         left      <- (json \ "left").validate[Option[JsObject]]
         right     <- (json \ "right").validate[Option[JsObject]]
         result    <- (left , right) match {
             case (Some(l), Some(r)) => for { leftnode  <- buildTreeNode(l)
                                              rightNode <- buildTreeNode(r)
                                        } yield Node(leaf, leftnode, rightNode)
             case (None   , None   ) => JsSuccess(leaf)
             case (_      , _      ) => JsError("left or right is missing")
         }
    } yield result

代码尝试在operation下找到valuedata字段。如果这些行失败,则计算停止并返回指示erorr的错误消息。成功后,计算继续并尝试查找左侧和右侧字段。如果它们存在并且有效JsObject,它们将被递归地解析。如果不存在,则此节点是叶子。否则,出现错误。

这段代码虽然易于阅读,但却执行了大量的错误处理,没有异常并且返回的错误消息并不是很糟糕