检查一个对象是否在json4s / lift-json中有一个字段

时间:2014-02-09 21:48:25

标签: json scala lift-json json4s

我有一些带有一些字段的json,我想检查它们中是否有一些存在。我正在提取值并针对JNothing测试它,但它太冗长了:

val json: JValue = ...

val jsonIsType1 = (json \ "field1") != JNothing && (json \ "field2") != JNothing

是否有更简洁的方法使用json4s / lift-json检查json对象中是否存在字段?理想情况如下:

val jsonIsType1 = json.has("field1") && json.has("field2")

2 个答案:

答案 0 :(得分:18)

JValue没有'has'操作符,但Scala的implicits功能允许您添加该功能而不会有太多麻烦。

以下是一个例子:

implicit class JValueExtended(value: JValue) {
  def has(childString: String): Boolean = {
    if ((value \ childString) != JNothing) {
      true
    } else {
      false
    }
  }
}

用法示例:

scala> val json = Json.parse("""{"field1": "ok", "field2": "not ok"}""")

scala> json.has("field1")
res10: Boolean = true

答案 1 :(得分:2)

您还可以将多个读取/验证步骤组合在一起以便理解。以下是两个函数,一个返回Option[_],另一个返回Boolean。第一个允许也使用数据,而后者只进行验证。

import org.json4s.jackson.JsonMethods._

val text =
  """
    |{
    |  "foo": "bar",
    |  "baz": "fnord",
    |  "qux": true
    |}
  """.stripMargin

val json = parse(text)

def readFoo(x: JValue): Option[(String, String, Boolean)] = for {
  JObject(_) <- x.toOption
  JString(foo) <- (x \ "foo").toOption
  JString(baz) <- (x \ "baz").toOption
  JBool(qux) <- (x \ "qux").toOption
  if (qux == true)
} yield (foo, baz, qux)

def validateOnly(x: JValue): Boolean = (for {
  JObject(_) <- x.toOption
  JString(foo) <- (x \ "foo").toOption
  JString(baz) <- (x \ "baz").toOption
  JBool(qux) <- (x \ "qux").toOption
  if (qux == true)
} yield true) getOrElse false

println(readFoo(json))            // Some((bar,fnord,true))
println(readFoo(json).isDefined)  // true
println(validateOnly(json))       // true