Skip to content

Commit

Permalink
More convenient operations for JSONValues (#1123)
Browse files Browse the repository at this point in the history
* More convenient operations for JSONValues

* Add test cases
  • Loading branch information
takezoe committed Jun 6, 2020
1 parent 4bf5cfb commit 4675f09
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 8 deletions.
75 changes: 75 additions & 0 deletions airframe-json/src/main/scala/wvlet/airframe/json/package.scala
Expand Up @@ -62,6 +62,36 @@ package object json {
case JSONObject(x) => x.map(x => (x._1, x._2.value)).toMap
}
}

def isNull: Boolean = {
jsonValue == JSONNull
}

def toStringValue: String = {
jsonValue.asInstanceOf[JSONString].v
}
def toDoubleValue: Double = {
jsonValue.asInstanceOf[JSONDouble].v
}
def toLongValue: Long = {
jsonValue.asInstanceOf[JSONLong].v
}
def toBooleanValue: Boolean = {
jsonValue.asInstanceOf[JSONBoolean].v
}
def toArrayValue: IndexedSeq[JSONValue] = {
jsonValue.asInstanceOf[JSONArray].v
}
def toObjectValue: Map[String, JSONValue] = {
jsonValue.asInstanceOf[JSONObject].v.toMap
}

def apply(name: String): JSONValue = {
jsonValue.asInstanceOf[JSONObject].get(name).get
}
def apply(i: Int): JSONValue = {
jsonValue.asInstanceOf[JSONArray].v(i)
}
}

implicit class JSONValueSeqOps(val jsonValues: Seq[JSONValue]) extends AnyVal {
Expand All @@ -76,5 +106,50 @@ package object json {
def value: Any = {
jsonValues.head.value
}

def toStringValues: Seq[String] = {
jsonValues.map(_.asInstanceOf[JSONString].v)
}
def toDoubleValues: Seq[Double] = {
jsonValues.map(_.asInstanceOf[JSONDouble].v)
}
def toLongValues: Seq[Long] = {
jsonValues.map(_.asInstanceOf[JSONLong].v)
}
def toBooleanValues: Seq[Boolean] = {
jsonValues.map(_.asInstanceOf[JSONBoolean].v)
}
def toArrayValues: Seq[IndexedSeq[JSONValue]] = {
jsonValues.map(_.asInstanceOf[JSONArray].v)
}
def toObjectValues: Seq[Map[String, JSONValue]] = {
jsonValues.map(_.asInstanceOf[JSONObject].v.toMap)
}

def toStringValue: String = {
jsonValues.head.asInstanceOf[JSONString].v
}
def toDoubleValue: Double = {
jsonValues.head.asInstanceOf[JSONDouble].v
}
def toLongValue: Long = {
jsonValues.head.asInstanceOf[JSONLong].v
}
def toBooleanValue: Boolean = {
jsonValues.head.asInstanceOf[JSONBoolean].v
}
def toArrayValue: IndexedSeq[JSONValue] = {
jsonValues.head.asInstanceOf[JSONArray].v
}
def toObjectValue: Map[String, JSONValue] = {
jsonValues.head.asInstanceOf[JSONObject].v.toMap
}

def apply(name: String): JSONValue = {
jsonValues.head.asInstanceOf[JSONObject].get(name).get
}
def apply(i: Int): JSONValue = {
jsonValues.head.asInstanceOf[JSONArray].v(i)
}
}
}
43 changes: 35 additions & 8 deletions airframe-json/src/test/scala/wvlet/airframe/json/JSONTest.scala
Expand Up @@ -12,7 +12,7 @@
* limitations under the License.
*/
package wvlet.airframe.json
import wvlet.airframe.json.JSON.{JSONArray, JSONLong, JSONNumber, JSONObject}
import wvlet.airframe.json.JSON._
import wvlet.airspec.AirSpec

/**
Expand Down Expand Up @@ -40,16 +40,43 @@ class JSONTest extends AirSpec {
}

def `JSON DSL`: Unit = {
val json: Json = """{"user": [{ "id": 1, "name": "a" }, { "id": 2, "name": "b" }]}"""
val json: Json = """{"user": [{ "id": 1, "name": "a", "flag": true }, { "id": 2, "name": "b", "flag": null }]}"""
val jsonValue = JSON.parse(json)

val id = (jsonValue / "user" / "id")(0).value
id shouldBe 1
val ids = (jsonValue / "user" / "id").values
ids shouldBe Seq(1, 2)

val name = (jsonValue / "user" / "name")(1).value
name shouldBe "b"
val id1 = (jsonValue / "user" / "id")(0).value
id1 shouldBe 1

val users = (jsonValue / "user").value
users shouldBe Seq(Map("id" -> 1, "name" -> "a"), Map("id" -> 2, "name" -> "b"))
val id2 = jsonValue("user")(1)("id").toLongValue
id2 shouldBe 2

val name1 = jsonValue("user")(0)("name").toStringValue
name1 shouldBe "a"

val name2 = (jsonValue / "user" / "name")(1).value
name2 shouldBe "b"

val flag1 = jsonValue("user")(0)("flag").toBooleanValue
flag1 shouldBe true

val flag2 = jsonValue("user")(1)("flag")
flag2.isNull shouldBe true

val users1 = (jsonValue / "user").value
users1 shouldBe Seq(Map("id" -> 1, "name" -> "a", "flag" -> true), Map("id" -> 2, "name" -> "b", "flag" -> null))

val users2 = (jsonValue / "user").toArrayValue
users2.length shouldBe 2
users2(0).toObjectValue shouldBe Map("id" -> JSONLong(1), "name" -> JSONString("a"), "flag" -> JSONBoolean(true))
users2(1).toObjectValue shouldBe Map("id" -> JSONLong(2), "name" -> JSONString("b"), "flag" -> JSONNull)
}

def `Extract nested properties by JSON DSL`: Unit = {
val json: Json = """{"user": [{ "values": {"value": "a"} }, { "values": {"value": "b"} }]}"""
val values = JSON.parse(json) / "user" / "values" / "value"

values.map(_.toStringValue) shouldBe Seq("a", "b")
}
}

0 comments on commit 4675f09

Please sign in to comment.