I inherited a legacy Scalatra application which offers a REST API. The serialisation of the returned object works perfectly if the returned object is a case class build on other case classes. But if return a object created from a Java or Scala class it is not serialised by Scalatra. I will get only the result of Object.toString(). So what do I need to do serialise also non case classes properly?
Here is my class
class Snafu(sna: String, foo: String) {
}
and this is my servlet:
class HealthServlet(implicit inj: Injector)
extends ScalatraServlet with SLF4JLogging
with JacksonJsonSupport
with Injectable with InternalViaLocalhostOnlySupport {
protected implicit val jsonFormats: Formats = DefaultFormats
val healthStateCheck = inject[HealthStateCheck]
before("/") {
}
get("/") {
Ok(new Snafu("4", "2"))
}
}
Non case class serialization isn't supported by default in json4s. You'll need to add a CustomSerializer for your classes.
class IntervalSerializer extends CustomSerializer[Interval](format => (
{
// Deserialize
case JObject(JField("start", JInt(s)) :: JField("end", JInt(e)) :: Nil) =>
new Interval(s.longValue, e.longValue)
},
{
// Serialize
case x: Interval =>
JObject(JField("start", JInt(BigInt(x.startTime))) ::
JField("end", JInt(BigInt(x.endTime))) :: Nil)
}
))
You'll also need to add those serializers to the jsonFormats being used.
protected implicit lazy val jsonFormats: Formats = DefaultFormats + FieldSerializer[Interval]()
Here's the example from the json4s documentation modified to show a working servlet returning serialized json from a regular class.
import org.json4s._
import org.json4s.JsonAST.{JInt, JField, JObject}
import org.scalatra.json.JacksonJsonSupport
class Interval(start: Long, end: Long) {
val startTime = start
val endTime = end
}
class IntervalSerializer extends CustomSerializer[Interval](format => (
{
// Deserialize
case JObject(JField("start", JInt(s)) :: JField("end", JInt(e)) :: Nil) =>
new Interval(s.longValue, e.longValue)
},
{
// Serialize
case x: Interval =>
JObject(JField("start", JInt(BigInt(x.startTime))) ::
JField("end", JInt(BigInt(x.endTime))) :: Nil)
}
))
class IntervalServlet extends ScalatraServlet with ScalateSupport with JacksonJsonSupport {
get("/intervalsample") {
contentType = "application/json"
val interval = new Interval(1, 2)
Extraction.decompose(interval)
}
protected implicit lazy val jsonFormats: Formats = DefaultFormats + FieldSerializer[Interval]()
}