4

いくつかのフィールドを持つ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")
4

2 に答える 2

20

JValue には「has」演算子はありませんが、Scala の暗黙の機能により、あまり問題なく機能を追加できます。

その例を次に示します。

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

使用例:

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

scala> json.has("field1")
res10: Boolean = true
于 2014-02-09T23:18:34.697 に答える
2

理解のために複数の読み取り/検証ステップを組み合わせることもできます。以下に 2 つの関数を示します。1 つは an を返し、Option[_]もう 1 つは a を返します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
于 2014-02-10T14:02:24.573 に答える