Json body 转换为密封特性
Json body converted to sealed trait
我有戏!可以接收 json body 作为 3 或 4 种形式的端点(我尝试使用通用类型,但不起作用)。
控制器:
def getChartData = Action.async(parse.json) { request =>
// ERROR: can not cast JsValue to type ChartDataRequest (which is sealed trait)
service.getChartData(request.body.asInstanceOf[ChartDataRequest]).map {
data => Ok(Json.toJson(data))
}.recover {
case _ => InternalServerErrror
}
}
服务:
def getChartData(request: ChartDataRequest): Future[data_type] = {
if (request.isInstanceOf[PieChartRequest]) {
//
} else if (request.isInstanceOf[BarChartRequest]) {
//
} else {
//
}
}
dtos:
sealed trait ChartDataRequest
final case class PieChartRequest(field1: String, field2: String, ....)
extends ChartDataRequest
final case class BarChartRequest(field1: String, field2: String, ....)
extends ChartDataRequest
找到了使用sealed traits的方案,但是做的不好
在这一点上,我无法将JsValue
类型转换为ChartDataRequest
类型。我可以在我的 json 中使用字段“classType
”,然后使用匹配模式创建指定的 object(PieDataRequest
或 BarDataRequest
),但我认为这不是最好的解决方案。
在我发送 objects 作为 json body 的所有控制器方法中,我使用了播放验证器,但有同样的问题,我将其从代码中删除。
// ChartDataRequest can have PieDataRequest or BarDataRequest type
request.body.validate[ChartDataRequest] match {
case JsSuccess(value, _) => // call the service
case JsError(_) => Future(BadRequest("Invalid json body"))
}
谢谢
你可以关注这个:
sealed trait ChartDataRequest
final case class PieChartRequest(field1: String) extends ChartDataRequest
final case class BarChartRequest(field2: String) extends ChartDataRequest
final case object WrongData extends ChartDataRequest
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val ChartDataRequests: Reads[ChartDataRequest] = {
val pc = Json.reads[PieChartRequest]
val bc = Json.reads[BarChartRequest]
__.read[PieChartRequest](pc).map(x => x: ChartDataRequest) |
__.read[BarChartRequest](bc).map(x => x: ChartDataRequest)
}
def getChartData(request: ChartDataRequest) = {
request match {
case _: PieChartRequest =>
Future("PieChartRequest")(defaultExecutionContext)
case _: BarChartRequest =>
Future("BarChartRequest")(defaultExecutionContext)
case _ =>
Future("WrongData")(defaultExecutionContext)
}
}
def getChartDataAction = Action.async(parse.json) { request =>
// you can separate this to a new function
val doIt = request.body.asOpt[JsObject].fold[ChartDataRequest](
WrongData
){
jsObj =>
jsObj.asOpt[ChartDataRequest].fold[ChartDataRequest](
WrongData
)(identity)
}
getChartData(doIt).map {
data => Ok(Json.toJson(data))
}(defaultExecutionContext).recover {
case _ => InternalServerError
}(defaultExecutionContext)
}
我有戏!可以接收 json body 作为 3 或 4 种形式的端点(我尝试使用通用类型,但不起作用)。
控制器:
def getChartData = Action.async(parse.json) { request =>
// ERROR: can not cast JsValue to type ChartDataRequest (which is sealed trait)
service.getChartData(request.body.asInstanceOf[ChartDataRequest]).map {
data => Ok(Json.toJson(data))
}.recover {
case _ => InternalServerErrror
}
}
服务:
def getChartData(request: ChartDataRequest): Future[data_type] = {
if (request.isInstanceOf[PieChartRequest]) {
//
} else if (request.isInstanceOf[BarChartRequest]) {
//
} else {
//
}
}
dtos:
sealed trait ChartDataRequest
final case class PieChartRequest(field1: String, field2: String, ....)
extends ChartDataRequest
final case class BarChartRequest(field1: String, field2: String, ....)
extends ChartDataRequest
找到了
在这一点上,我无法将JsValue
类型转换为ChartDataRequest
类型。我可以在我的 json 中使用字段“classType
”,然后使用匹配模式创建指定的 object(PieDataRequest
或 BarDataRequest
),但我认为这不是最好的解决方案。
在我发送 objects 作为 json body 的所有控制器方法中,我使用了播放验证器,但有同样的问题,我将其从代码中删除。
// ChartDataRequest can have PieDataRequest or BarDataRequest type
request.body.validate[ChartDataRequest] match {
case JsSuccess(value, _) => // call the service
case JsError(_) => Future(BadRequest("Invalid json body"))
}
谢谢
你可以关注这个:
sealed trait ChartDataRequest
final case class PieChartRequest(field1: String) extends ChartDataRequest
final case class BarChartRequest(field2: String) extends ChartDataRequest
final case object WrongData extends ChartDataRequest
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val ChartDataRequests: Reads[ChartDataRequest] = {
val pc = Json.reads[PieChartRequest]
val bc = Json.reads[BarChartRequest]
__.read[PieChartRequest](pc).map(x => x: ChartDataRequest) |
__.read[BarChartRequest](bc).map(x => x: ChartDataRequest)
}
def getChartData(request: ChartDataRequest) = {
request match {
case _: PieChartRequest =>
Future("PieChartRequest")(defaultExecutionContext)
case _: BarChartRequest =>
Future("BarChartRequest")(defaultExecutionContext)
case _ =>
Future("WrongData")(defaultExecutionContext)
}
}
def getChartDataAction = Action.async(parse.json) { request =>
// you can separate this to a new function
val doIt = request.body.asOpt[JsObject].fold[ChartDataRequest](
WrongData
){
jsObj =>
jsObj.asOpt[ChartDataRequest].fold[ChartDataRequest](
WrongData
)(identity)
}
getChartData(doIt).map {
data => Ok(Json.toJson(data))
}(defaultExecutionContext).recover {
case _ => InternalServerError
}(defaultExecutionContext)
}