playframework - play anorm, create a model from json without passing anorm PK value in the json -
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 = "")
the above 2 controller & model, when send user data [id, name, email] json using angular js, creates user object in database. should able create when input [name, email] or [name] email null. if i'm not wrong should adjust these in reads , writes method of user, it?.
also, can have 2 reads/writes different pursposes, if how can achieved - throw light. thanks.
one issue fixed following:
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)) }
now email can null, id - pk[long]
i did not compile this, should work:
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)) }
basically take id option[long
] did email. check if set , if yes create pk instance id[long](id
) , if not provide notassigned
pk singleton instance.
additional tip
alternatively can try use
implicit val jsonformatter = json.format[user]
it create reads
, writes
directly @ compile time. there 2 problem if using anorm object directly:
first need format 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) }
second not work, if not send id @ all, not value null, client needs send {"id": null, "name": "tim"}
because not try call pkformatter handle jsundefined, gives "validate.error.missing-path" error
if don't want send null ids cannot use macro json.format[user]
Comments
Post a Comment