[2.1 master] Please help with Json.reads Json.writes macros

3,577 views
Skip to first unread message

Daniel Dietrich

unread,
Nov 14, 2012, 5:49:55 PM11/14/12
to play-fr...@googlegroups.com
Hi,

according to Json.scala there are two macros: Json.reads and Json.writes.

Has anyone an idea / could give me a hint, please, why the following code does not work? (See comments for compiler errors.)

Thanks in advance

Daniel


import play.api.libs.json.Json


case class User(name: String, age: Int, active: Boolean)


object JsonTest extends App {


  implicit val userReads = Json.reads[User] // not found: value JsPath

  implicit val userWrites = Json.writes[User] // not found: value JsPath


  val daniel = User("daniel", 37, true)

  /*

   * Multiple markers at this line

   * - not enough arguments for method toJson: (implicit tjs: play.api.libs.json.Writes[User])play.api.libs.json.JsValue.

   *   Unspecified value parameter tjs.

   * - No Json deserializer found for type User. Try to implement an implicit Writes or Format for this type.

   */

  val userJson = Json.toJson(daniel)

  val user = Json.fromJson(userJson)


  assert(user == daniel)


}


Pascal Voitot Dev

unread,
Nov 15, 2012, 4:53:10 AM11/15/12
to play-fr...@googlegroups.com
Please import a few more stuff in your scope. You need the default implicits...

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._

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/-/6PK11GKoIlkJ.
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.

Daniel Dietrich

unread,
Nov 15, 2012, 5:27:50 AM11/15/12
to play-fr...@googlegroups.com
thx - I will try it

Daniel Dietrich

unread,
Nov 15, 2012, 3:32:58 PM11/15/12
to play-fr...@googlegroups.com
Merci bien! It works.

But I must not import the Reads._ stuff, otherwise I got the following error at Json.fromJson(userJson):

Multiple markers at this line

- diverging implicit expansion for type play.api.libs.json.Reads[T] starting with method ArrayReads in trait DefaultReads

- ambiguous implicit values:  both value userReads in object json of type => play.api.libs.json.Reads[json.User]  and object IntReads in trait DefaultReads of type play.api.libs.json.Reads.IntReads.type  match expected type play.api.libs.json.Reads[T]

- diverging implicit expansion for type play.api.libs.json.Reads[T] starting with method ArrayReads in trait DefaultReads

- not enough arguments for method fromJson: (implicit fjs: play.api.libs.json.Reads[T])play.api.libs.json.JsResult[T]. Unspecified value parameter fjs.


Anyway, as of this discussion the json stuff is currently subject of refactoring...


import play.api.libs.json._

import play.api.libs.json.util._

// import play.api.libs.json.Reads._

import play.api.libs.json.Writes._


object json {


  case class User(name: String, age: Int, active: Boolean)


  implicit val userReads = Json.reads[User]       //> userReads  : play.api.libs.json.Reads[json.User] = play.api.libs.json.Reads$

                                                  //| $anon$8@518f5824

  implicit val userWrites = Json.writes[User]     //> userWrites  : play.api.libs.json.OWrites[json.User] = play.api.libs.json.OWr

                                                  //| ites$$anon$2@388ee016


  val daniel = User("daniel", 37, true)           //> daniel  : json.User = User(daniel,37,true)

  val userJson = Json.toJson(daniel)              //> userJson  : play.api.libs.json.JsValue = {"name":"daniel","age":37,"active":

                                                  //| true}

  val user = Json.fromJson(userJson)              //> user  : play.api.libs.json.JsResult[json.User] = JsSuccess(User(daniel,37,tr

                                                  //| ue),)


  user.get == daniel                              //> res0: Boolean = true

Pascal Voitot Dev

unread,
Nov 15, 2012, 4:10:21 PM11/15/12
to play-fr...@googlegroups.com
Do you mean that if you import both Reads._ and Writes._ you get errors?

Pascal


--
 
 

Daniel Dietrich

unread,
Nov 15, 2012, 4:27:48 PM11/15/12
to play-fr...@googlegroups.com
yes.

I compiled Play20 master with scala 2.10.0-RC1
and run eclipse juno sr1 with scala ide (which uses scala 2.10.0-RC2).

My eclipse project files are created with the 'play eclipse' command.

- Daniel

Pascal Voitot Dev

unread,
Nov 15, 2012, 4:33:20 PM11/15/12
to play-fr...@googlegroups.com
Strange!
I'm going to test that!

thanks
Pascal



- Daniel

--
 
 

Pascal Voitot Dev

unread,
Nov 16, 2012, 11:30:16 AM11/16/12
to play-fr...@googlegroups.com
Hello all,

After some macro headaches, I finally succeeded in adding fully qualified classes everywhere and also embedding functional.syntax._ import in generated code.

Everything is in this pull req:
https://github.com/playframework/Play20/pull/546

Now you can just write:

import play.api.libs.json.Json

implicit val userReads = Json.reads[User]

Nothing more is required from the user except the implicits he created himself.

regards
Pascal

Daniel Dietrich

unread,
Nov 16, 2012, 11:41:56 AM11/16/12
to play-fr...@googlegroups.com
Wow - thank you very much!
 
Daniel

Pascal Voitot Dev

unread,
Nov 16, 2012, 11:48:22 AM11/16/12
to play-fr...@googlegroups.com

Daniel,
Please test again with your case and let see if you still have a pb!

Pascal

Le 16 nov. 2012 17:42, "Daniel Dietrich" <cafe...@googlemail.com> a écrit :
Wow - thank you very much!
 
Daniel

--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 12:58:13 PM11/16/12
to play-fr...@googlegroups.com
Pascal,

could you give me a hint how I get the changes of your pull request to my local git repository?

Daniel Dietrich

unread,
Nov 16, 2012, 1:07:12 PM11/16/12
to play-fr...@googlegroups.com
ok, of cause I clone the forked repo git://github.com/mandubian/Play20.git

Pascal Voitot Dev

unread,
Nov 16, 2012, 1:09:08 PM11/16/12
to play-fr...@googlegroups.com

Git clone master
Go in framework Dir
Run ./build
Then "publish-local" in console
Then point your play alias to bin/play
Run your project with this play

Pascal

Le 16 nov. 2012 18:58, "Daniel Dietrich" <cafe...@googlemail.com> a écrit :
Pascal,

could you give me a hint how I get the changes of your pull request to my local git repository?

--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 5:44:50 PM11/16/12
to play-fr...@googlegroups.com
It works great! Tested it as Scala App and as Worksheet.

Adding import play.api.libs.json.Writes._ does not affect the code.

Adding import play.api.libs.json.Reads._ does introduce the following compile time error (which should be ok!):

Multiple markers at this line

- ambiguous implicit values: both value userReads in object JsonTest of type => play.api.libs.json.Reads[User] and object IntReads in trait DefaultReads of 

type play.api.libs.json.Reads.IntReads.type match expected type play.api.libs.json.Reads[T]

- ambiguous implicit values: both value userReads in object JsonTest of type => play.api.libs.json.Reads[User] and object IntReads in trait DefaultReads of 

type play.api.libs.json.Reads.IntReads.type match expected type play.api.libs.json.Reads[T]

- diverging implicit expansion for type play.api.libs.json.Reads[T] starting with method ArrayReads in trait DefaultReads

- not enough arguments for method fromJson: (implicit fjs: play.api.libs.json.Reads[T])play.api.libs.json.JsResult[T]. Unspecified value parameter fjs.

- diverging implicit expansion for type play.api.libs.json.Reads[T] starting with method ArrayReads in trait DefaultReads

- not enough arguments for method fromJson: (implicit fjs: play.api.libs.json.Reads[T])play.api.libs.json.JsResult[T]. Unspecified value parameter fjs.



Here is the Worksheet using only the import of Json:

import play.api.libs.json.Json


object json {


  case class User(name: String, age: Int, active: Boolean)


  implicit val userReads = Json.reads[User]       //> userReads  : play.api.libs.json.Reads[json.User] = play.api.libs.json.Reads$

                                                  //| $anon$8@144aa0ce

  implicit val userWrites = Json.writes[User]     //> userWrites  : play.api.libs.json.OWrites[json.User] = play.api.libs.json.OWr

                                                  //| ites$$anon$2@5cac6a45

Daniel Dietrich

unread,
Nov 16, 2012, 6:44:39 PM11/16/12
to play-fr...@googlegroups.com
Pascal,

do you think your pull request will make it into Play 2.1-final since it is already tagged as RC1?

Pascal Voitot Dev

unread,
Nov 16, 2012, 6:55:34 PM11/16/12
to play-fr...@googlegroups.com
Actually, you don't need to import Reads._ and Writes._ as those implicits are automatically resolved by Scala compiler as soon as you work with a Reads[A] or a Writes[A].

I'm going to correct this in the samples and tests because this is something I've discovered recently :D

and yes naturally, my pull req will be integrated before final (if other devs find it good :D)
I think a few more optimization in the macro code might still be done...

regards
Pascal


--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 7:00:54 PM11/16/12
to play-fr...@googlegroups.com
This all sounds great. I definitely also have to dive into this macro stuff - even if it could result in macro headaches sometimes ;-)

regards

Daniel

Pascal Voitot Dev

unread,
Nov 16, 2012, 7:09:13 PM11/16/12
to play-fr...@googlegroups.com
good luck ;)



--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 7:31:04 PM11/16/12
to play-fr...@googlegroups.com
Btw - with the current 2.1-RC1 tag (Utils.scala where added to play.api.libs.functional) my Json example (see above) does not work any more (tried all possible combinations of imports)...

Pascal Voitot Dev

unread,
Nov 16, 2012, 7:33:51 PM11/16/12
to play-fr...@googlegroups.com
if you need to use functional syntax implicits to use combinators to write your own Reads[T] (not generated by macros) using operator "and" for ex, you must import play.api.libs.functional.syntax._ since yesterday!

Pascal



On Sat, Nov 17, 2012 at 1:31 AM, Daniel Dietrich <cafe...@googlemail.com> wrote:
Btw - with the current 2.1-RC1 tag (Utils.scala where added to play.api.libs.functional) my Json example (see above) does not work any more (tried all possible combinations of imports)...

--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 7:42:57 PM11/16/12
to play-fr...@googlegroups.com
yes, but I don't use the internal dsl / combinators. It's just reading / writing a case class without additional magic.

For completeness here is the code with corresponding exceptions - but please don't investigate further - the pull request is already in the pipeline...

regards

Daniel


import play.api.libs.json._

import play.api.libs.json.util._

import play.api.libs.json.Reads._

import play.api.libs.json.Writes._


case class User(name: String, age: Int, active: Boolean)


object JsonTest extends App {


  /* value and is not a member of play.api.libs.json.Reads[String]

   * Note: implicit value userReads is not applicable here because it comes

   *       after the application point and it lacks an explicit result type

   */

  implicit val userReads = Json.reads[User]

  

  /*

   * value and is not a member of play.api.libs.json.OWrites[String]

   * Note: implicit value userWrites is not applicable here because it comes

   *       after the application point and it lacks an explicit result type

   */

  implicit val userWrites = Json.writes[User]


  val daniel = User("daniel", 37, true)

  

  /*

   * Multiple markers at this line

   * - No Json deserializer found for type User. Try to implement an implicit Writes or Format for this type.

   * - not enough arguments for method toJson: (implicit tjs: play.api.libs.json.Writes[User])play.api.libs.json.JsValue.

   *   Unspecified value parameter tjs.

   * - No Json deserializer found for type User. Try to implement an implicit Writes or Format for this type.

   * - not enough arguments for method toJson: (implicit tjs: play.api.libs.json.Writes[User])play.api.libs.json.JsValue.

   *   Unspecified value parameter tjs.

   */

  val userJson = Json.toJson(daniel)

  val user = Json.fromJson(userJson)


  println(user.get == daniel)


}


Pascal Voitot Dev

unread,
Nov 16, 2012, 7:53:07 PM11/16/12
to play-fr...@googlegroups.com
you shouldn't import those 4:

import play.api.libs.json._

import play.api.libs.json.util._

import play.api.libs.json.Reads._

import play.api.libs.json.Writes._


but just: (only because you use macros)


import play.api.libs.json.Json





--
 
 

Daniel Dietrich

unread,
Nov 16, 2012, 8:05:28 PM11/16/12
to play-fr...@googlegroups.com

argh - ok got it. it works with these imports (as expected) -  thx



import play.api.libs.functional.syntax._

import play.api.libs.json._

Pascal Voitot Dev

unread,
Nov 16, 2012, 8:15:36 PM11/16/12
to play-fr...@googlegroups.com
but why do you need Writes._ and even functional.syntax._?
Seeing the code sample, this shouldn't be mandatory.
Don't worry if no answer, it's time to sleep it's very late here ;)



--
 
 

Daniel Dietrich

unread,
Nov 17, 2012, 4:53:59 AM11/17/12
to play-fr...@googlegroups.com
yes, I got some sleep, too - we live in the same timezone :)

I'm now on the Play20-master branch again (my 'golden source'). Here are the additional imports are needed...

Daniel Dietrich

unread,
Nov 18, 2012, 8:36:38 PM11/18/12
to play-fr...@googlegroups.com
[a little bit off topic]

Pascal,

I'm working on a generic DAO abstraction layer for Slick w/ Play and took the chance to create my first Scala macro :)

Unfortunately I'm stuck at 99,9% of the macro, where a method with a named parameter has to be called via macro.

If you are interested:

http://stackoverflow.com/questions/13446528/howto-model-named-parameters-in-method-invocations-with-scala-macros

Regards

- Daniel

On Saturday, November 17, 2012 1:09:45 AM UTC+1, Pascal wrote:
good luck ;)
 

Pascal Voitot Dev

unread,
Nov 19, 2012, 3:16:01 AM11/19/12
to play-fr...@googlegroups.com
I'll think about it... instead of using copy, you could also try to use constructor directly in the macro...

But just one point: be really careful when you choose macro instead of a classic language pattern. I really consider macro as a tool but not as a patch to solve problems that shouldn't be solved in this way... (I don't say your choice is bad, just to consider macros very precisely ;) )

regards
Pascal


 

--
 
 

Daniel Dietrich

unread,
Nov 19, 2012, 11:13:29 AM11/19/12
to play-fr...@googlegroups.com
Thank you. It was very interesting to investigate the new Scala macros & reflection features. I see also the pros/cons of changing the default behavior of the compiler - and with that the semantics of the Scala language. One important thing of Scala is its conciseness. With macros things can be done even more concise. That was also my driver in this case. I'm curious if folks will create a Scala_A, Scala_B, ... in the near future - à la 'pimp my language'...
 
greets
Daniel
 

Jay

unread,
Nov 23, 2012, 9:49:26 PM11/23/12
to play-fr...@googlegroups.com
I'm having issues with using the new json libs.  I wrote the following spec

import play.api.test._
import play.api.test.Helpers._
import play.api.libs.json.Json

import models._
import json.JsonFormats._

class JsonFormatsSpec extends Specification {
 
 
"JsonFormats" should {
   
   
"equals the user jay" in {
      val profile
= Profile("Jay Cain")
     
      val settings
= Settings()
     
      val jay
= User("cain...@gmail.com", profile, settings, "hash", None, false)
     
      val userJson
= Json.toJson(jay)  
     
      val user
= Json.fromJson(userJson)
     
...
   
}
   
 
}
}

when I run the test I get the following error:

[error] /Users/cainj/sandbox/pong/test/json/ApplicationSpec.scala:30: diverging implicit expansion for type play.api.libs.json.Reads[T]
[error] starting with method ArrayReads in trait DefaultReads
[error]       val user = Json.fromJson(userJson)
[error]                               ^


Any insight would be helpful.  I'm tried the play master and play-2.1-RC-1

Thx,

Jay

Jay

unread,
Nov 23, 2012, 11:33:52 PM11/23/12
to play-fr...@googlegroups.com
I just looked at the quote above more closely, I need to clone  git://github.com/mandubian/Play20.git

Daniel Dietrich

unread,
Nov 24, 2012, 1:43:57 AM11/24/12
to play-fr...@googlegroups.com
Hi Jay,

it should work with the 2.1 master / rc1 too. Just add these imports and to implicit val's:

Anyway, as of this discussion the json stuff is currently subject of refactoring...


import play.api.libs.json._
import play.api.libs.json.util._


// import play.api.libs.json.Reads._
import play.api.libs.json.Writes._

implicit val userReads = Json.reads[User]

implicit val userWrites = Json.writes[User]


There's a pending pull request which reduces the imports to the minimum...

- Daniel

Pascal Voitot Dev

unread,
Nov 26, 2012, 11:34:35 AM11/26/12
to play-fr...@googlegroups.com
Please try this
import play.api.libs.functional.syntax._

instead of
import play.api.libs.json.util._

(the package has been moved just before releasing RC1)
(FYI in master this import is no more required as well as Writes._)

regards
Pascal




On Mon, Nov 26, 2012 at 5:27 PM, Cristi Boariu <cristi...@gmail.com> wrote:
Hi Daniel,

I used your latest imports (whithout Read) but I receive the same warnings similar to you, my code is:

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Writes._

object AddressBean extends Controller with RestTrait {

  implicit val addressWrites = Json.writes[Address]

  implicit val addressReads = Json.reads[Address]
}

warning: value and is not a member of play.api.libs.json.Reads[Option[Int]] Note: implicit value addressReads is not 
 applicable here because it comes after the application point and it lacks an explicit result type

I'm wondering if you have added anything else to fix these...

Basically I have to make this JSON stuff to work with 2.1-RC1 because my project uses scala 2.10 so can't go back to 2.09... Is there any chance to solve this issue?

Thanks!

--
 
 

Cristi Boariu

unread,
Nov 26, 2012, 11:36:08 AM11/26/12
to play-fr...@googlegroups.com
Wow, it works, thanks.......

Thibault

unread,
Nov 30, 2012, 1:03:31 PM11/30/12
to play-fr...@googlegroups.com
I'm getting a compiler error when the case class has a companion object. I use scala 2.10.0-RC3 and the very latest Play20, built from master branch.

Here is a quick gist to reproduce the problem: https://gist.github.com/4177343

Excellent job with Play 2.1, thanks a bunch! I'm now rewritting http://lichess.org with all that new goodness, it's a lot of fun.

Thibault

unread,
Nov 30, 2012, 1:21:48 PM11/30/12
to play-fr...@googlegroups.com
Interrestingly enouth, I get the same error when I do the mapping manually, without using the macro magic! See that gist https://gist.github.com/4177529

I'm sure there is a better solution than renaming all my companion objects ;) But what could it be?

Pascal Voitot Dev

unread,
Nov 30, 2012, 1:29:04 PM11/30/12
to play-fr...@googlegroups.com

Hi
Did you have same for problem with Scala 2.10RC2 ?

Pascal

--
 
 

Pascal Voitot Dev

unread,
Nov 30, 2012, 6:15:41 PM11/30/12
to play-fr...@googlegroups.com

If you use Foo.apply, it should work.

As soon as you create object for case class, case class hidden features are overriden by compiler...
Concerning the macro, I think we could improve it a bit and go around this problem.

Pascal

--
 
 

Thibault

unread,
Dec 1, 2012, 12:04:20 PM12/1/12
to play-fr...@googlegroups.com
Indeed manual mapping with (Foo.apply _) is working.

I tried the macro style with scala 2.10.0-RC2, and no difference, I get the same compiler error.

Thibault

unread,
Dec 3, 2012, 3:57:58 PM12/3/12
to play-fr...@googlegroups.com
No it's the same thing with several attributes. Sorry for the delay, I'm travelling at the moment.

On Sunday, December 2, 2012 12:35:59 AM UTC+1, Grégory Bougeard wrote:
As @mandubian told me, there is a limitation on case class containing one and only one attribute.
Maybe this is your case...

deVIAntCoDE

unread,
Jan 3, 2013, 9:35:56 AM1/3/13
to play-fr...@googlegroups.com
Yes I have the same problem as well. I have had to rename my companion objects as well. What is the progress on the issue though?
I found this ticket relating to it but no comment on it so far.

Pascal Voitot Dev

unread,
Jan 3, 2013, 9:37:55 AM1/3/13
to play-fr...@googlegroups.com
I haven't tested with latest scala 2.10.0 but it might be a problem in Scala directly...

pascal


--
 
 

Reply all
Reply to author
Forward
0 new messages