1

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.

Dariusz Mydlarz
  • 2,940
  • 6
  • 31
  • 59

3 Answers3

1

I think, that the easiest way is to update your case classes like

case class Adding(value: Int, operation: String = "Adding") 
case class Removing (value: Int, operation: String = "Removing") 

Another way is to update your jsonFormats with custom serializer, I found example of jsons custom serialization here

Dmitry Meshkov
  • 921
  • 7
  • 20
1

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)
    }

  }

}
Stefan Ollinger
  • 1,577
  • 9
  • 16
0

json_conversion.scala file we created the trait SimpleMongoDbJsonConversion and we use this in MyScalatraServlet.scala file, see the example below.

json_conversion.scala

package com.example.app

import org.scalatra._
import com.mongodb.casbah.Imports._

trait SimpleMongoDbJsonConversion extends ScalatraBase with ApiFormats {

  def renderMongo = {
    case dbo: DBObject =>
      contentType = formats("json")
      dbo.toString

    case xs: TraversableOnce[_] =>
      contentType = formats("json")
      val l = xs map (x => x.toString) mkString(",")
      "[" + l + "]"

  }: RenderPipeline

  override protected def renderPipeline = renderMongo orElse super.renderPipeline

}

MyScalatraServlet.scala

package com.example.app

import org.scalatra._
import com.mongodb.casbah.Imports._

class MyScalatraMongoServlet(mongoColl: MongoCollection) extends MyScalatraWebAppStack with SimpleMongoDbJsonConversion {

  get("/") {
    <html>
      <body>
        <h1>Hello, world!</h1>
        Say <a href="hello-scalate">hello to Scalate</a>.
      </body>
    </html>
  }

  post("/insert") {
    val key = params("key")
    val value = params("value")
    val newObj = MongoDBObject(key->value)
    mongoColl += newObj
  }

  get("/users") {
    mongoColl.find()
    for { x <- mongoColl } yield x
  }

}
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133