Json 主体转换为密封特征 [英] Json body converted to sealed trait

查看:23
本文介绍了Json 主体转换为密封特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有戏!可以接收 json 主体作为 3 或 4 种形式的端点(我尝试使用泛型类型,但不起作用).

I have a Play! endpoint which can receive a json body as 3 or 4 forms (I tried using generic type, but not working).

控制器:

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

我在这里找到了使用密封特征的解决方案,但不能这样做很好.

I found here the solution to use sealed traits, but can't do it well.

此时,我无法将JsValue 转换为ChartDataRequest 类型.我可以使用字段classType";在我的 json 中,然后使用匹配模式创建指定的对象(PieDataRequestBarDataRequest),但我认为这不是最好的解决方案.

In this point, I can not convert the JsValue to ChartDataRequest type. I can use a field "classType" in my json and then using the match pattern to create the specified object (PieDataRequest or BarDataRequest) but I think this is not the best solution.

在我将对象作为 json 主体发送的所有控制器方法中,我使用了播放验证器,但遇到了同样的问题,我将其从代码中删除.

Inside all my controller methods where I send objects as json body, I use the play validator, but have the same problem, and I removed it from code.

// 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 主体转换为密封特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆