4
object Users  {

  implicit object UserReads extends Reads[User] {
    def reads(json: JsValue) = JsSuccess(User(
      Id((json \ "id").as[String].toLong),
      (json \ "name").as[String],
      (json \ "email").as[String]
  }
  implicit object UserWrites extends Writes[User] {
    def writes(user: User) = JsObject(Seq(
      "id" -> JsNumber(user.id.get),
      "name" -> JsString(user.name),
      "email" -> Json.toJson(user.email)
  }

  def view(id: Long) = Action { implicit request =>
    Ok(Json.toJson(User.find(id)))
  }

  def all() = Action { implicit request =>
    Ok(Json.toJson(User.findAll()))
  }

  def save = Action(parse.json) { request =>
    val userJson = request.body
    val user = userJson.as[User]
    try {
      User.create(user)
      Ok("Saved")
    } catch {
      case e: IllegalArgumentException => BadRequest("Error")
    }
  }
}


case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: String = "")

以上两个是我的控制器和模型,当我使用 Angular JS 将用户数据 [id, name, email] 发送为 json 时,它会在数据库中创建用户对象。但是当我仅输入 [name, email] 或仅输入 [name] 时,它应该能够创建,因为 email 可能为空。如果我没记错的话,我应该在用户的读写方法中调整这些,是吗?

此外,我们是否可以针对不同的目的进行两次读取/写入,如果可以,如何实现 - 抛出一些亮点。谢谢。

解决了以下问题的一个问题:

case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: Option[String])

implicit object UserReads extends Reads[User] {
    def reads(json: JsValue) = JsSuccess(User(
      Id((json \ "id").as[String].toLong),
      (json \ "name").as[String],
      (json \ "email").asOpt[String])
  }
  implicit object UserWrites extends Writes[User] {
    def writes(user: User) = JsObject(Seq(
      "id" -> JsNumber(user.id.get),
      "name" -> JsString(user.name),
      "email" -> Json.toJson(user.email))
  }

现在 email 可以为空,但是 id - PK[Long]

4

2 回答 2

2

我没有编译这个,但它应该可以工作:

case class User(
  id: Pk[Long] = NotAssigned,
  name: String = "",
  email: Option[String])

implicit object UserReads extends Reads[User] {
    def reads(json: JsValue) = JsSuccess(User(
      (json \ "id").asOpt[Long].map(id => Id[Long](id)).getOrElse(NotAssigned)
      (json \ "name").as[String],
      (json \ "email").asOpt[String])
  }
  implicit object UserWrites extends Writes[User] {
    def writes(user: User) = JsObject(Seq(
      "id" -> JsNumber(user.id.get),
      "name" -> JsString(user.name),
      "email" -> Json.toJson(user.email))
  }

基本上,您将 id 视为Option[Long] ,就像您对电子邮件所做的那样。然后检查它是否已设置,如果是,则使用Id[Long](id) 创建 Pk 实例,如果没有,则提供NotAssignedPk 单例实例。

附加提示

或者,您可以尝试使用

implicit val jsonFormatter = Json.format[User]

它将在编译时直接为您创建Reads和。Writes如果您直接使用 anorm 对象,则会出现两个问题:

首先,您需要 Pk[Long] 的格式

implicit object PkLongFormat extends Format[Pk[Long]] {
  def reads(json: JsValue): JsResult[Pk[Long]] = {
    json.asOpt[Long].map {
      id => JsSuccess(Id[Long](id))
    }.getOrElse(JsSuccess(NotAssigned))
  }
  def writes(id: Pk[Long]): JsNumber = JsNumber(id.get)
}

其次,如果您根本不发送 id,即使值为 null,它也不起作用,因此您的客户端需要发送{"id": null, "name": "Tim"},因为它甚至不尝试调用可以处理 JsUndefined 的 PkFormatter,而只是给您一个“ validate.error.missing-path”错误

如果您不想发送空 ID,则不能使用宏Json.format[User]

于 2013-06-15T15:03:42.823 回答
0

类型在形式和功能anorm.Pk上几乎完全一样。scala.Option避免写具体的Reads和它可能包含Writes的所有类型。遵循and实现的示例如下:OptionReadsOptionWrites

implicit def PkWrites[T](implicit w: Writes[T]): Writes[Pk[T]] = new Writes[Pk[T]] {
  def writes(o: Pk[T]) = o match {
    case Id(value) => w.writes(value)
    case NotAssigned => JsNull
  }
}

implicit def PkReads[T](implicit r: Reads[T]): Reads[Pk[T]] = new Reads[Pk[T]] {
  def reads(js: JsValue): JsResult[Pk[T]] =
    r.reads(js).fold(e => JsSuccess(NotAssigned), v => JsSuccess(Id(v)))
}

这样一来,你就支持每T一个有相应Reads[T]or的东西,并且在处理andWrites[T]时更加可靠。IdNotAssigned

于 2014-06-04T00:32:04.060 回答