如何将 json 转换为 Play Framework REST API 中的实体
How to convert a json to an entity in Play Framework REST API
我刚刚开始使用 scala 和 play 框架,并坚持这个看似简单的问题。
我有一个 REST 端点,我将 post 一些 Json 对象指向该端点。 Json 对象需要转换为实体。
实体被声明为 case classes 类型,接收到的 Json 可以是 case classes 的任何类型。
我的问题是,我无法将 Json 转换为相应的实体类型,因为(根据教程)我需要在每个字段的验证中写入 implicit Reads
定义。
例如
implicit val emailReads: Reads[Email] = (
(JsPath \ "from").read[String] and
(JsPath \ "subject").read[String]
)(Email.apply _)
适用于示例案例 class 电子邮件。但是当我遇到这样的情况时 classes :
abstract class Event
case class OneEventType(type : String) extends Event
case class TwoEventType(type : String, attribute : SomeType) extends Event
并且控制器方法基于事件工作:
def events = Action(BodyParsers.parse.json) { request =>
val eventReceived = request.body.validate[Event]
//do something
Ok(Json.obj("status" ->"OK"))
}
我将如何验证事件并构建正确的事件对象,因为在 Reads 方法中我需要指定每个字段?
我想你可以,为阅读添加一个自定义过程。假设属性是 Int 类型:
abstract class Event
case class OneEventType(type : String) extends Event
case class TwoEventType(type : String, attribute : Int) extends Event
implicit val eventReader: Reads[Event] = (
(JsPath \ "type").read[String] and
(JsPath \ "attribute").readNullable[Int]
)((typeOp, attributeOp) => {
if (attribute.isEmpty) OneEventType(typeOp.get())
else TwoEventType(typeOp.get(), attributeOp.get())
})
(现在无法测试,所以我不确定它是否开箱即用)。
这应该有效,
implicit val st: Reads[Event] = new Reads[Event] {
def reads(json: JsValue): JsResult[Event] = {
json match {
case JsObject(Seq(("type", JsString(type)), ("attribute", JsString(attribute)))) => JsSuccess(TwoEventType(type, attribute))
case o: JsObject if (o.value.get("type").isDefined) => JsSuccess(OneEventType(o.value.get("type")))
case a: Any => JsError(a.toString())
}
}
}
我刚刚开始使用 scala 和 play 框架,并坚持这个看似简单的问题。
我有一个 REST 端点,我将 post 一些 Json 对象指向该端点。 Json 对象需要转换为实体。
实体被声明为 case classes 类型,接收到的 Json 可以是 case classes 的任何类型。
我的问题是,我无法将 Json 转换为相应的实体类型,因为(根据教程)我需要在每个字段的验证中写入 implicit Reads
定义。
例如
implicit val emailReads: Reads[Email] = (
(JsPath \ "from").read[String] and
(JsPath \ "subject").read[String]
)(Email.apply _)
适用于示例案例 class 电子邮件。但是当我遇到这样的情况时 classes :
abstract class Event
case class OneEventType(type : String) extends Event
case class TwoEventType(type : String, attribute : SomeType) extends Event
并且控制器方法基于事件工作:
def events = Action(BodyParsers.parse.json) { request =>
val eventReceived = request.body.validate[Event]
//do something
Ok(Json.obj("status" ->"OK"))
}
我将如何验证事件并构建正确的事件对象,因为在 Reads 方法中我需要指定每个字段?
我想你可以,为阅读添加一个自定义过程。假设属性是 Int 类型:
abstract class Event
case class OneEventType(type : String) extends Event
case class TwoEventType(type : String, attribute : Int) extends Event
implicit val eventReader: Reads[Event] = (
(JsPath \ "type").read[String] and
(JsPath \ "attribute").readNullable[Int]
)((typeOp, attributeOp) => {
if (attribute.isEmpty) OneEventType(typeOp.get())
else TwoEventType(typeOp.get(), attributeOp.get())
})
(现在无法测试,所以我不确定它是否开箱即用)。
这应该有效,
implicit val st: Reads[Event] = new Reads[Event] {
def reads(json: JsValue): JsResult[Event] = {
json match {
case JsObject(Seq(("type", JsString(type)), ("attribute", JsString(attribute)))) => JsSuccess(TwoEventType(type, attribute))
case o: JsObject if (o.value.get("type").isDefined) => JsSuccess(OneEventType(o.value.get("type")))
case a: Any => JsError(a.toString())
}
}
}