如何在 Scalatra 中将对象类型序列化为 JSON?

How to serialize object type to JSON in Scalatra?

我是 Scalatra 的新手。我有一个带有 JacksonJsonSupport 的 servlet,它为带有对象列表的 REST 端点提供服务。

class OperationsController extends MyappStack with JacksonJsonSupport {

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

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

OperationAddingRemoving case classes 实现。 如何将特定的 class 添加到 GET / 响应中?我想得到回应:

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

而不是

[
  {
     "value": 100
  }
]

其中 Adding 是扩展 Operation.

的 class

我认为,最简单的方法是像

一样更新您的案例 类
case class Adding(value: Int, operation: String = "Adding") 
case class Removing (value: Int, operation: String = "Removing") 

另一种方法是使用自定义序列化程序更新您的 jsonFormats,我找到了 jsons 自定义序列化的示例 here

对于多态值,json4s 可以将具体类型添加为附加字段。这称为 "type hint":

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

例如使用 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)
    }

  }

}

json_conversion.scala 文件我们创建了特征 SimpleMongoDbJsonConversion 并在 MyScalatraServlet.scala 文件中使用它,请参见下面的示例。

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
  }

}