dmydlarz dmydlarz - 2 months ago 22
JSON Question

How to serialize object type to JSON in Scalatra?

I am a newbie in Scalatra. I have a servlet with JacksonJsonSupport which serves REST endpoint with list of objects.

class OperationsController extends MyappStack with JacksonJsonSupport {

before() {
contentType = formats("json")
}

get("/") {
Data.operations
}
}


The
Operation
is implemented by either
Adding
or
Removing
case classes.
How do I add to the
GET /
response the specific class to the value? I would like to get as a response:

[
{
"operation": "Adding",
"value": 100
}
]


Instead of

[
{
"value": 100
}
]


Where
Adding
is a class that extends
Operation
.

Answer Source

For polymorphic values json4s can add the concrete type as an additional field. This is called a "type hint":

[{
    "jsonClass": "Adding",
    "value": 10
}, {
    "jsonClass": "Adding",
    "value": 20
}, {
    "jsonClass": "Removing",
    "value": 20
}]

This is for example using the ShortTypeHints:

import org.json4s.{ShortTypeHints, DefaultFormats}
import org.scalatra.ScalatraServlet
import org.scalatra.json.JacksonJsonSupport
import org.scalatra.test.specs2.MutableScalatraSpec

sealed trait Operation
case class Adding(value: Int) extends Operation
case class Removing(value: Int) extends Operation

class json1 extends MutableScalatraSpec {

  mount(new ScalatraServlet with JacksonJsonSupport {

    def typeHints = new ShortTypeHints(List(
      classOf[Adding], classOf[Removing]
    ))

    implicit lazy val jsonFormats = DefaultFormats + typeHints

    before() {
      contentType = formats("json")
    }

    get("/") {
      List(
        Adding(10),
        Adding(20),
        Removing(20)
      )
    }

  }, "/*")

  "Should return a list of operations" in {

    get("/", headers = Seq("Content-type" -> "application/json")) {
      println(body)
      status should beEqualTo(200)
    }

  }

}