目前我正在使用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中以字符串的形式。
答案 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)
}
}
}