如何在Scala Play Framework

时间:2015-05-20 12:40:37

标签: json scala playframework

目前我正在使用Play Framework工作一个Web应用程序,现在我正在开发一个JSON API。不幸的是,我在使用内置的JSON库将对象解析为JSON时遇到了问题。我们有以下特征,它定义了Shipment的类型和要使用的解析器。还有一个具有ShipmentType的案例类,因此我们知道每种类型的用户使用哪个解析器。并且有一种方法可以将所有存储的货件作为列表返回。

trait ShipmentType {

  def parser(list: List[String]): ShipmentTypeParser

}

object ShipmentTypeA extends ShipmentType {

  def parser(list: List[String]) = new ShipmentTypeAParser(list)

}

object ShipmentTypeB extends ShipmentType {

  def parser(list: List[String]) = new ShipmentTypeBParser(list)

}

object ShipmentTypeC extends ShipmentType {

  def parser(list: List[String]) = new ShipmentTypeCParser(list)

}

case class Shipment(id: Long, name: String, date: Date, shipmentType: Type)

要编写此JSON,我使用以下隐式val:

import play.api.libs.json._
import play.api.libs.functional.syntax._

def findAll = Action {
    Ok(Json.toJson(Shipments.all))
}
implicit val shipmentWrites: Writes[Shipment] = (
    (JsPath \ "id").write[Option[Long]] and
    (JsPath \ "name").write[String] and
    (JsPath \ "date").write[Date] and
    (JsPath \ "shipmentType").write[ShipmentType]
)(unlift(Shipment.unapply))

接下来,我们需要为ShipmentType额外添加一个:

implicit val shipmentTypeWriter: Writes[ShipmentType] = ()

但是我遇到了困难,我似乎找不到如何为ShipmentType定义编写器的方法。

我还尝试根据Play Framework文档的另一个页面将它们定义如下:

implicit val shipmentWrites: Writes[Shipment] = Json.writes[Shipment]
implicit val shipmentTypeWrites: Writes[ShipmentType] =Json.writes[ShipmentType]

然而,这也失败了,因为我得到如下错误:"找不到未应用的功能"。 任何人都想知道如何为此实现一个Writer?最好是在json中以字符串的形式。

1 个答案:

答案 0 :(得分:0)

我创建了一个工作示例:

trait ShipmentTypeParser

class ShipmentTypeAParser(list: List[String]) extends ShipmentTypeParser

class ShipmentTypeBParser(list: List[String]) extends ShipmentTypeParser

object ShipmentTypeA extends ShipmentType {
  override def parser(list: List[String]) = new ShipmentTypeAParser(list)
}

object ShipmentTypeB extends ShipmentType {
  override def parser(list: List[String]) = new ShipmentTypeBParser(list)
}


object Models {


  implicit val shipmentTypeWrites = new Format[ShipmentType] {
    override def writes(shipmentType: ShipmentType): JsValue = 
        JsString(shipmentType.getClass.getName)


    override def reads(json: JsValue): JsResult[ShipmentType] = json match {
      case JsString(className) =>
        Try(Class.forName(className)) match {
          case Success(c) =>
            JsSuccess(c.getField("MODULE$").get(c).asInstanceOf[ShipmentType])
          case Failure(th) =>
            JsError(th.getMessage)
        }
      case _ =>
        JsError(json.toString)
    }
  }

  implicit val shipmentWrites: Format[Shipment] = Json.format[Shipment]
}

trait ShipmentType {
  def parser(list: List[String]): ShipmentTypeParser
}


case class Shipment(id: Long, name: String, date: Date, shipmentType: ShipmentType)

在测试中进行测试:

class JsonSpec extends FlatSpec with Matchers {
  "Shipment " should " be convert to json and from " in {
    import Models._
    val shipment = Shipment(3, "33", new Date(), ShipmentTypeA)
    val jsonShipment = Json.toJson(shipment)
    println(jsonShipment)
    val fromJson = Json.fromJson[Shipment](jsonShipment)
    fromJson match{
      case JsSuccess(shipmentFromJson,_) =>
        shipmentFromJson shouldBe shipment
      case _ =>
        fail(fromJson.toString)
    }
  }
}