Last active
November 28, 2017 12:38
-
-
Save swallez/50bf22eddce10161f2e226da57a896ea to your computer and use it in GitHub Desktop.
Experimenting a Scala DSL to create JSON objects with Jackson
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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