Ho un json con alcuni campi e voglio controllare se alcuni di essi sono presenti. Sto estraendo il valore e testandolo contro JNothing, ma è troppo prolisso:
val json: JValue = ...
val jsonIsType1 = (json "field1") != JNothing && (json "field2") != JNothing
C'è un modo più compatto per verificare la presenza di un campo in un oggetto json usando json4s / lift-json? Idealmente qualcosa come:
val jsonIsType1 = json.has("field1") && json.has("field2")
risposte:
14 per risposta № 1JValue non ha un operatore "ha", ma il potere degli impliciti di Scala ti consente di aggiungere quella funzionalità senza troppi problemi.
Ecco un esempio di questo:
implicit class JValueExtended(value: JValue) {
def has(childString: String): Boolean = {
if ((value childString) != JNothing) {
true
} else {
false
}
}
}
Esempio di utilizzo:
scala> val json = Json.parse("""{"field1": "ok", "field2": "not ok"}""")
scala> json.has("field1")
res10: Boolean = true
2 per risposta № 2
È inoltre possibile combinare più passaggi di lettura / convalida all'interno di a per comprensione. Di seguito sono due funzioni, una che restituisce un Option[_]
e uno che restituisce a Boolean
. Il primo permette di lavorare anche con i dati, mentre il secondo solo la validazione.
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