Skip to content

Instantly share code, notes, and snippets.

@swallez
Last active November 28, 2017 12:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swallez/50bf22eddce10161f2e226da57a896ea to your computer and use it in GitHub Desktop.
Save swallez/50bf22eddce10161f2e226da57a896ea to your computer and use it in GitHub Desktop.
Experimenting a Scala DSL to create JSON objects with Jackson
import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import com.fasterxml.jackson.databind.node._
import scala.language.implicitConversions
object JacksonDSL {
// Builder objects using varargs
object ObjectNode {
def apply(props: (String, JsonNode)*): ObjectNode = {
val obj = new ObjectNode(JsonNodeFactory.instance)
props.foreach { case (k, v) => obj.set(k, v) }
obj
}
def parse(json: String): JsonNode = new ObjectMapper().readTree(json)
}
object ArrayNode {
def apply(elems: JsonNode*): ArrayNode = {
val arr = new ArrayNode(JsonNodeFactory.instance)
elems.foreach(arr.add)
arr
}
}
// Implicit conversions between basic types and their JsonNode equivalents
implicit def toJson(v: Int): IntNode = IntNode.valueOf(v)
implicit def toJson(v: Boolean): BooleanNode = BooleanNode.valueOf(v)
implicit def toJson(v: String): TextNode = TextNode.valueOf(v)
implicit def toJson(v: Double): DoubleNode = DoubleNode.valueOf(v)
// Extensions methods to map MissingNode to Option
implicit class PimpedJsonNode(val node: JsonNode) extends AnyVal {
def toOption: Option[JsonNode] = if (node.isMissingNode) None else Some(node)
def maybeAt(path: String): Option[JsonNode] = node.at(path).toOption
}
//---------------------------------------------------------------------------------------
def main(args: Array[String]): Unit = {
val foo = ObjectNode(
"prop1" -> 1,
"prop2" -> "bar",
"ga" -> 2.0,
"bu" -> ObjectNode(
"zo" -> 1,
"meu" -> false
),
"foo" -> ArrayNode(1, 2, 3)
)
require (foo.path("prop1").asInt == 1)
require (foo.path("prop3").isMissingNode)
require (foo.at("/bu/zo").toOption.contains(IntNode.valueOf(1)))
require (foo.maybeAt("/bu/zo").contains(IntNode.valueOf(1)))
require (foo.at("/bu/zooo").toOption.isEmpty)
require (foo.maybeAt("/bu/zooo").isEmpty)
// More complex example, with added variables, embedding a json string, etc
val anArray = Seq(1, 2, 3)
val aJsonString = """ { "bar": "baz" } """
val json = ObjectNode(
"foo" -> ObjectNode.parse(aJsonString),
"arr" -> ArrayNode(anArray.map(toJson): _*)
)
require (json.toString == """{"foo":{"bar":"baz"},"arr":[1,2,3]}""")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment