[2.0] concatenating JSValues

1,176 views
Skip to first unread message

danielkol

unread,
Mar 7, 2012, 6:32:58 PM3/7/12
to play-fr...@googlegroups.com
So I currently am able to implicitly convert a single object to Json using the Play Framework libraries.  The following is an example of definitions for two of them.

  implicit object UserFormat extends Format[User] {
    def reads(json: JsValue): User = User(
      (json \ "id").asInstanceOf[Pk[Long]],
      (json \ "email").as[String])

    def writes(u: User): JsValue = JsObject(List(
      "id" -> JsInteger(u.id.get),
      "email" -> JsString(u.email)
    ))
  }

implicit object GroupFormat extends Format[UserGroup] {

  def reads(json: JsValue): UserGroup = UserGroup(
    (json \ "userId").as[Long],
    (json \ "groupId").as[Long],
    (json \ "groupName").as[String]
  )

  def writes(ug: UserGroup): JsValue = JsObject(List(
    "userId" -> JsInteger(ug.userId),
    "groupId" -> JsNumber(ug.groupId),
    "groupName" -> JsBoolean(ug.groupNamel)
  ))
}


So currently in my code I can define

toJson(someUser)

and

toJson(someUserGroup)

Is there an easy way to define an implicit formatter for a type (User, UserGroup) for writing so I can implicitly call:

toJson((SomeUser, SomeUserGroup))

I ideally want to be able to call something like the following write def below (Obviously the + operator doesn't work in the following example)

  implicit object UserWithUserGroupFormat extends Format[(User, UserGroup)] {
    def reads(json: JsValue): ...

    def writes(uug: (User, UserGroup)): JsValue = toJson(uug._1) + toJson(uug._2)
  }


Pascal Voitot Dev

unread,
Mar 8, 2012, 2:38:45 AM3/8/12
to play-fr...@googlegroups.com
See below


Yes it should be possible.

you can merge 2 JsObject:

toJson(someUser) ++ toJson(someUserGroup)

But merging User and UserGroup in the same object seems weird to me...

maybe you want to write

JsObject(Seq(
  ("user", toJson(someUser)),
  ("group", toJson(someUserGroup))
))
 
regards
pascal


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To view this discussion on the web visit https://groups.google.com/d/msg/play-framework/-/GMApKentuYcJ.
To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.

Derek Williams

unread,
Mar 7, 2012, 7:01:18 PM3/7/12
to play-fr...@googlegroups.com
On Wed, Mar 7, 2012 at 4:32 PM, danielkol <dko...@toclarity.com> wrote:
Is there an easy way to define an implicit formatter for a type (User, UserGroup) for writing so I can implicitly call:

toJson((SomeUser, SomeUserGroup))

I ideally want to be able to call something like the following write def below (Obviously the + operator doesn't work in the following example)

  implicit object UserWithUserGroupFormat extends Format[(User, UserGroup)] {
    def reads(json: JsValue): ...

    def writes(uug: (User, UserGroup)): JsValue = toJson(uug._1) + toJson(uug._2)
  }


JsObject contains the '++' method for merging two objects together:

So then you should be able to do something like this (untested):

implicit def mergeWrites[A: JsonFormat, B: JsonFormat]: Writes[(A, B)] = new Writes[(A, B)] {
  def writes(pair: (A, B)): JsValue = toJson(pair._1).as[JsObject] ++ toJson(pair._2).as[JsObject]
}

Or make a non generic version:

impicit object UserWithUserGroupWrites extends Writes[(User, UserGroup)] {
  def writes(pair: (User, UserGroup)): JsValue = toJson(pair._1).as[JsObject] ++ toJson(pair._2).as[JsObject]
}

You will end up with both 'id' and 'userId' in your json of course

--
Derek Williams

Pascal Voitot Dev

unread,
Mar 8, 2012, 4:39:41 AM3/8/12
to play-fr...@googlegroups.com
yes you're right: I forgot the ".as[JsObject]" ;)

Pascal

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
Reply all
Reply to author
Forward
0 new messages