[2.1 RC2 Scala] Json 2 Json: reduce

362 views
Skip to first unread message

David P.

unread,
Jan 18, 2013, 10:43:59 PM1/18/13
to play-fr...@googlegroups.com
Hey guys,

I've been searching around Google and the forums, but I haven't found any answers to this one yet. Could be that I'm just missing something silly...

I've basically been following the documentation here, trying to get some Coast-to-Coast JSON going. Specifically, I was looking at the example on the bottom and following the format provided there.


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

object MyController extends Controller {
  ....

  private val authResponse2authInfo = (
    ....
    (__ \ 'email        ).json.copyFrom ((__ \ 'profile \ 'email            ).json.pick) and
    (__ \ 'displayName  ).json.copyFrom ((__ \ 'profile \ 'displayName      ).json.pick) and
    (__ \ 'formattedName).json.copyFrom ((__ \ 'profile \ 'name \ 'formatted).json.pick) and
    (__ \ 'photo        ).json.copyFrom ((__ \ 'profile \ 'photo            ).json.pick)
  ) reduce
}


Gets me this error:

could not find implicit value for parameter reducer: play.api.libs.functional.Reducer[play.api.libs.json.JsObject,B]

Changing the last line to:

  ).reduce[JsObject, JsObject]

Produced the following:

could not find implicit value for parameter reducer: play.api.libs.functional.Reducer[play.api.libs.json.JsObject,play.api.libs.json.JsObject]


Any assistance on this would be greatly appreciated.

Thanks,
  David

David P.

unread,
Jan 19, 2013, 1:53:01 AM1/19/13
to play-fr...@googlegroups.com
Ok... So, I'm starting to figure some of this out. Hurray for scala docs!

After adding:

import Reads.JsObjectReducer

And then setting the following my Build.scala, project settings:

    scalacOptions ++= Seq("-feature", "-language:postfixOps")

Reduce has begun working.


Now, does anyone know how to make certain paths Optional?  As it is, I've discovered that the "or" operator is very useful. Consider:

(__ \ 'email).json.copyFrom (
  (__ \ '
profile \ 'verifiedEmail).json.pick or
  (__ \ '
profile \ 'email).json.pick
)

But what am I supposed to do on the "left hand" side of the equation? I'm looking for photo to be completely optional here.

(__ \ 'photo).json.copyFrom((__ \ 'profile \ 'photo).json.pick)

I've tried using nullable... Seems like it ought to be able to go in there somewhere. But I usually end up getting something like this:

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

Any ideas?

Pascal Voitot Dev

unread,
Jan 19, 2013, 5:54:19 AM1/19/13
to play-fr...@googlegroups.com
Yes I know this one which is a limitation of current implicit imports.
When using JSON transformers with .reduce,  you must import

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

to get the reducers!

By the way, you can reduce a JsObject but also a JsArray

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

scala> val arrReads: Reads[JsArray] = (
     |   (__ \ 'field1).json.pick and
     |   (__ \ 'field2).json.pick and
     |   (__ \ 'field3).json.pick
     | ).reduce
arrReads: play.api.libs.json.Reads[play.api.libs.json.JsArray] = play.api.libs.json.Reads$$anon$8@79c11750


Pascal



Any assistance on this would be greatly appreciated.

Thanks,
  David

--
 
 

Pascal Voitot Dev

unread,
Jan 19, 2013, 6:11:36 AM1/19/13
to play-fr...@googlegroups.com
On Sat, Jan 19, 2013 at 7:53 AM, David P. <patr...@gmail.com> wrote:
Ok... So, I'm starting to figure some of this out. Hurray for scala docs!

After adding:

import Reads.JsObjectReducer


Yes when reducing Json transformer, you must import Reads._ to have both Reducer[JsObject/JsArray] (and monoids also).
I should upgrade a bit the doc about imports because there are a few missing precisions sometimes.

 
And then setting the following my Build.scala, project settings:

    scalacOptions ++= Seq("-feature", "-language:postfixOps")

Reduce has begun working.


postfixops is just a 2.10 new warning when you don't want the warning about:


  private val authResponse2authInfo = (
    ....
    (__ \ 'email        ).json.copyFrom ((__ \ 'profile \ 'email            ).json.pick) and
    (__ \ 'displayName  ).json.copyFrom ((__ \ 'profile \ 'displayName      ).json.pick) and
    (__ \ 'formattedName).json.copyFrom ((__ \ 'profile \ 'name \ 'formatted).json.pick) and
    (__ \ 'photo        ).json.copyFrom ((__ \ 'profile \ 'photo            ).json.pick)
  ) reduce
    ^^^^^^^
    POST FIX OP

Making it a method call removes the warning (even if I find it better using the post fix op)
  private val authResponse2authInfo = (
    ....
    (__ \ 'email        ).json.copyFrom ((__ \ 'profile \ 'email            ).json.pick) and
    (__ \ 'displayName  ).json.copyFrom ((__ \ 'profile \ 'displayName      ).json.pick) and
    (__ \ 'formattedName).json.copyFrom ((__ \ 'profile \ 'name \ 'formatted).json.pick) and
    (__ \ 'photo        ).json.copyFrom ((__ \ 'profile \ 'photo            ).json.pick)
  ).reduce
   ^^^^^^^
   method call
 

Now, does anyone know how to make certain paths Optional?  As it is, I've discovered that the "or" operator is very useful. Consider:

(__ \ 'email).json.copyFrom (
  (__ \ '
profile \ 'verifiedEmail).json.pick or
  (__ \ '
profile \ 'email).json.pick
)

But what am I supposed to do on the "left hand" side of the equation?

Not sure to understand what you want to do here with "left hand" side.

There is another interesting feature of Reads to remind.

Read[A] and Reads[B] => Reads[A ~ B]
Read[A] or Reads[B >: A] => Reads[A]
Read[A] keepAnd Reads[B] => Reads[A] (keep left but both are verified)
Read[A] andKeep Reads[B] => Reads[B] (keep right but both are verified)

 
I'm looking for photo to be completely optional here.

(__ \ 'photo).json.copyFrom((__ \ 'profile \ 'photo).json.pick)

I've tried using nullable... Seems like it ought to be able to go in there somewhere. But I usually end up getting something like this:

what do you mean by completely optional? Do you want field "photo" not to appear in final JSON if profile/photo is missing in originated JSON ?
Maybe the following will fit your need:

(__ \ 'photo).json.copyFrom((__ \ 'profile \ 'photo).json.pick) orElse Reads.pure(Json.obj())

it reads the photo and if failed, it puts an empty JsObject. So when you reduce it, you don't have the photo field in final JSON.


regards
Pascal
 

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

Any ideas?

--
 
 

David P.

unread,
Jan 19, 2013, 10:42:26 AM1/19/13
to play-fr...@googlegroups.com
Hey Pascal,

Thank you for the responses.

Sorry about the confusion: when I was asking about the "left-hand side", I was referring to making "photo" completely optional. Most of the second message was about documenting how I got reduce working (in case anyone else ran into this) and showing off what I thought was a cool use of Or while implementing a Json transformer.

So yeah, I did mean that I wanted "photo" to not appear if it was missing in the original Json. Which, adding the "orElse Reads.pure(Json.obj())" did quite nicely. Thinking about it now, I would also be fine with it being null, or some other value representing None...

Maybe I'm still too used to the idea of marshaling Json into Case Classes.



Something else I've thought of recently. I didn't realize it until earlier in the week, but I don't think I've posted much here before (if at all). So let me introduce myself...

I've been very interested in the Play Framework for over a year now, but only really got into it once 2.0 was released. Until recently, I've been able to answer any question I had through thorough Googling. But I'm really excited by the whole Json Coast-to-Coast, Reactive Mongo, and the Iteratees concepts. I also think that combining those concepts with a MVC JS Client could be really powerful.

So, to everyone that's worked on it; thank you for this awesome web development framework. I think that in many respects, Play Framework is leading the way forward for how web applications should be written.

 - David P.

Pascal Voitot Dev

unread,
Jan 19, 2013, 2:08:54 PM1/19/13
to play-fr...@googlegroups.com
On Sat, Jan 19, 2013 at 4:42 PM, David P. <patr...@gmail.com> wrote:
Hey Pascal,

Thank you for the responses.

Sorry about the confusion: when I was asking about the "left-hand side", I was referring to making "photo" completely optional. Most of the second message was about documenting how I got reduce working (in case anyone else ran into this) and showing off what I thought was a cool use of Or while implementing a Json transformer.

So yeah, I did mean that I wanted "photo" to not appear if it was missing in the original Json. Which, adding the "orElse Reads.pure(Json.obj())" did quite nicely. Thinking about it now, I would also be fine with it being null, or some other value representing None...


I advise not to use null for a missing field in JSON. null is a valid value in JSON (mapped to JsNull in Play).
readNullable has been added to manage the fact that lots of API send null in their JSON but actually, it's not so nice.
 
Maybe I'm still too used to the idea of marshaling Json into Case Classes.


It's exactly what I explained in my article about Json coast-to-coast: we have been biased by class serialization... Let's think in a more objective way!
 


Something else I've thought of recently. I didn't realize it until earlier in the week, but I don't think I've posted much here before (if at all). So let me introduce myself...

I've been very interested in the Play Framework for over a year now, but only really got into it once 2.0 was released. Until recently, I've been able to answer any question I had through thorough Googling. But I'm really excited by the whole Json Coast-to-Coast, Reactive Mongo, and the Iteratees concepts. I also think that combining those concepts with a MVC JS Client could be really powerful.


Yes exactly! Don't hesitate to experiment, we are only beginning to use those concepts in real web apps so we will discover more cool features IMHO ;)
 
So, to everyone that's worked on it; thank you for this awesome web development framework. I think that in many respects, Play Framework is leading the way forward for how web applications should be written.


You're welcome dude, this is cool to hear this :D
 
 - David P.

--
 
 

Reply all
Reply to author
Forward
0 new messages