It's my first time using argonauts and only have a small knowledge of lenses (enough to get by). I've spent a while trying to figure out the problem myself but getting nowhere.
I'm trying to build a lens to get a JsonArray (of Strings) from some JSON. I can get as far as the Object that has the Array but not sure what to do from there.
The JSON looks like:
And my lens so far is this:
val hashtagsView = twitterEntitiesView >=> jsonObjectPL("hashtags") >=> jArrayPL
I'm not sure if that jArrayPL
is correct either. What I would like to do is just retrieve the text from the Array.
So to wrap up, can anyone help me in finding out how to construct a lens that looks into hashtags and then for each element of the array look into the text, finally getting a values as a JsonArray
.
Update:
With some help from Travis I have the following code compiling:
import argonaut._, Argonaut._
import monocle.std.list._, monocle.function.Each.each, monocle.function.Index.index
import scalaz._, Scalaz._
val \/-(json) = Parse.parse(rawJSON)
val lens = jObjectPrism
.composeOptional(index("hashtags"))
.composePrism(jArrayPrism)
.composeTraversal(each[List[Json], Json])
.composePrism(jObjectPrism)
.composeOptional(index("text"))
.composePrism(jStringPrism)
println(lens.getAll(json))
Unfortunately, I get a runtime error: scalaz.Scalaz$.ToEitherOps(Ljava/lang/Object;)Lscalaz/syntax/EitherOps;
starting at the line val \/-(json) = Parse.parse(rawJSON)
Thanks in advance!
Are you willing to use the Monocle lenses that Argonaut provides instead of the Scalaz lenses? If so, working with traversals is a lot nicer:
import argonaut._, Argonaut._
import monocle.function.{ each, index }, monocle.std.list._
import scalaz._, Scalaz._
val doc = """{
"hashtags": [
{ "indices": [0, 3], "text": "foo" },
{ "indices": [3, 6], "text": "bar" }
]
}"""
val \/-(json) = Parse.parse(doc)
val lens = jObjectPrism
.composeOptional(index("hashtags"))
.composePrism(jArrayPrism)
.composeTraversal(each[List[Json], Json])
.composePrism(jObjectPrism)
.composeOptional(index("text"))
.composePrism(jStringPrism)
And then:
scala> lens.getAll(json)
res0: List[argonaut.Argonaut.JsonString] = List(foo, bar)
scala> lens.modify(_ + " (new)")(json).spaces2
res1: String =
{
"hashtags" : [
{
"indices" : [
0,
3
],
"text" : "foo (new)"
},
{
"indices" : [
3,
6
],
"text" : "bar (new)"
}
]
}
And so on. You could do something similar with Scalaz lenses but it would take more work.