2014-02-09 28 views
0

我有一个带有字段的json,我想检查它们是否存在。我提取值和测试它反对JNothing,但实在是太冗长:检查一个对象是否在json4s/lift-json中有一个字段

val json: JValue = ... 

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

是否有使用json4s /升JSON来检查一个字段的JSON对象存在一个更紧凑的方式?理想的情况是这样的:

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

回答

12

JValue没有一个“有”操作,但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 
+0

这是接近我在找什么。 – douglaz

+0

喜欢它。让我补充一点简洁:隐式类JValueExtended(value:JValue)def has(childString:String):Boolean =(value \ childString)!= JNothing } –

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 
+0

非常好的解决方案,但如果我只是稍微矫枉过正想要知道一个字段是否存在,而不声明其他属性,如字段的类型。 – douglaz

+0

使用for-comprenhensions解开不同元素的好方法! – pianista

相关问题