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时,它会在数据库中创建User对象。但是当我只输入[name,email]或[name]时它应该可以创建,因为电子邮件可能为null。如果我没有错,我应该在User的读写方法中调整这些,是吗?。
另外,我们可以为不同的目标进行两次读/写操作,如果是这样的话,怎么能实现呢 - 抛出一些光。感谢。
以下内容确定了一个问题:
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))
}
现在电子邮件可以为null,但是id-PK [Long]
呢答案 0 :(得分: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实例,如果不是,则提供NotAssigned
Pk单例实例。
其他提示
或者您可以尝试使用
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"}
,因为它甚至没有尝试调用可以处理它的PkFormatter JsUndefined,但只是给你一个“validate.error.missing-path”错误
如果您不想发送空ID,则无法使用宏Json.format[User]
答案 1 :(得分:0)
类型anorm.Pk
在形式和功能上几乎与scala.Option
完全相同。避免为可能包含的所有类型编写具体的Reads
和Writes
。 OptionReads
和OptionWrites
实现之后的示例如下:
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]
的{{1}},并且在处理Writes[T]
和Id
时更可靠。< / p>