【问题标题】:Optional Json Body Parser可选的 Json 正文解析器
【发布时间】:2012-06-18 18:36:37
【问题描述】:

我正在尝试使用 PlayFramework 编写一个 DRY CRUD 宁静服务。这是它的代码。

def crudUsers(operation: String) = Action(parse.json) { request =>
 (request.body).asOpt[User].map { jsonUser =>
  try {
    DBGlobal.db.withTransaction {
      val queryResult = operation match {
        case "create" =>
           UsersTable.forInsert.insertAll(jsonUser)
           Json.generate(Map("status" -> "Success", "message" -> "Account inserted"))

        case "update" =>
           val updateQ = UsersTable.where(_.email === jsonUser.email.bind).map(_.forInsert)
           println(updateQ.selectStatement)
           updateQ.update(jsonUser)
           Json.generate(Map("status" -> "Success", "message" -> "Account updated"))

        case "retrieve" =>
           val retrieveQ = for(r <- UsersTable) yield r
           println(retrieveQ.selectStatement)
           Json.generate(retrieveQ.list)

        case "delete" =>
           val deleteQ = UsersTable.where(_.email === jsonUser.email)
           deleteQ.delete
           Json.generate(Map("status" -> "Success", "message" -> "Account deleted"))
      }
      Ok(queryResult)
    }
  } catch {
    case _ =>
      val errMsg: String = operation + " error"
      BadRequest(Json.generate(Map("status" -> "Error", "message" -> errMsg)))
  }
}.getOrElse(BadRequest(Json.generate(Map("status" -> "Error", "message" -> "error"))))

} }

我注意到更新、删除和创建操作运行良好。但是,检索操作失败并显示For request 'GET /1/users' [Invalid Json]。我很确定这是因为 JSON 解析器不能容忍在正文中没有传递 JSON 的 GET 请求。

有没有办法在不丢失我在这里开始的 DRY 方法的情况下对 GET/Retrieve 操作进行特殊处理?

【问题讨论】:

  • JSON 要求存在顶级 JSON 对象或 JSON 数组。 “无数据”不是有效的 JSON。见RFC4627JSON-text = object / array
  • 好的。谢谢。似乎另一种选择是构建一个更智能的解析器,它只能接受获取请求的文本内容。知道我该怎么做吗?

标签: scala playframework-2.0


【解决方案1】:

我的猜测是你拆分了你的方法,这样你就可以为有和没有 body 的方法创建不同的路由。

似乎即使将空字符串解析为JSON,代码的设计也无法正常工作。 map 方法不会被执行,因为没有用户。这将导致匹配操作永远不会被执行。

更新

既然你提到了 DRY,我会把它重构成这样的:

  type Operations = PartialFunction[String, String]

  val operations: Operations = {
    case "retrieve" =>
      println("performing retrieve")
      "retrieved"
    case "list" =>
      println("performing list")
      "listed"
  }

  def userOperations(user: User): Operations = {
    case "create" =>
      println("actual create operation")
      "created"
    case "delete" =>
      println("actual delete operation")
      "updated"
    case "update" =>
      println("actual update operation")
      "updated"
  }

  def withoutUser(operation: String) = Action {
    execute(operation, operations andThen successResponse)
  }

  def withUser(operation: String) = Action(parse.json) { request =>
    request.body.asOpt[User].map { user =>
      execute(operation, userOperations(user) andThen successResponse)
    }
      .getOrElse {
        errorResponse("invalid user data")
      }
  }  

  def execute(operation: String, actualOperation: PartialFunction[String, Result]) =
    if (actualOperation isDefinedAt operation) {
      try {
        DBGlobal.db.withTransaction {
          actualOperation(operation)
        }
      } catch {
        case _ => errorResponse(operation + " error")
      }
    } else {
      errorResponse(operation + " not found")
    }

  val successResponse = createResponse(Ok, "Success", _: String)
  val errorResponse = createResponse(BadRequest, "Error", _: String)

  def createResponse(httpStatus: Status, status: String, message: String): Result =
    httpStatus(Json.toJson(Map("status" -> status, "message" -> message)))

【讨论】:

    猜你喜欢
    • 2015-12-04
    • 2020-12-15
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    相关资源
    最近更新 更多