2014-02-09 6 views
0

У меня есть json с некоторыми полями, и я хочу проверить, присутствуют ли некоторые из них. Я извлечение значения и его испытание JNothing, но это слишком многословно:Проверьте, есть ли у объекта поле в json4s/lift-json

val json: JValue = ... 

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

Есть ли более компактный способ проверить наличие поля в объекте JSon с помощью json4s/подъемной JSON? В идеале что-то вроде:

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

ответ

12

JValue не имеет «имеет» оператора, но сила implicits в Scala позволяет добавить эту функциональность без особых проблем.

Вот пример того, что: пример

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 (значение: JValue) { def имеет (childString: String): Boolean = (значение \ 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

Отличный способ развернуть различные элементы, используя для-comprenhensions! – pianista

Смежные вопросы