I'm trying to create a scala function that converts a JsObject to one with a different structure.
All values are optional and so the function shouldn't throw an error if they don't appear on the input object.
I have the following code which works when I use .as[String]
on the lookups rather than asOpt
but I can't work out how to get this working with optional fields. I'm not sure how to convert from Option when creating the output object:
val input = Json.obj(
"title" -> "a book",
"author" -> Json.obj("name" -> "mr smith"),
"metadata" -> Json.obj("published" -> 10983920189403L))
case class Book(title: Option[String], author: Option[String], published: Option[Long])
def bookConvertor(inputObject: JsObject): JsObject = {
Try {
val title = (inputObject \ "title").asOpt[String]
val author = (inputObject \ "author" \ "name").asOpt[String]
val published = (inputObject \ "metadata" \ "published").asOpt[Long]
Book(title, author, published)
} match {
case Success(book) => {
JsObject(
Seq(
"title" -> JsString(book.title),
"author" -> JsString(book.author),
"published" -> JsString(book.published)
)
)
}
}
}
Any help would be great. I am new to Scala.
To convert from a Book
to a JsObject
, you can use play-json macros rather than doing it manually:
val writes: OWrites[Book] = Json.writes[Book]
val book: Book = ???
val jsObj: JsObject = Json.toJsObject(book)
If you wanted to do it manually, you could do something like this for each attribute:
...
"title" -> book.title.map(JsString(_)).getOrElse(JsNull)
...
But don't, let the library do the boring painful part for you :)