使用 Argonaut 透镜从 JSON 个包含 JSON 个对象的数组中提取值

Extracting values from JSON Array of JSON Objects using Argonaut Lenses

第一次用argonauts,对镜头的了解也很少(勉强过得去)。我花了一段时间试图自己找出问题,但一无所获。

我正在尝试构建一个镜头以从某些 JSON 获取 JsonArray(字符串)。我可以到达具有数组的对象,但不确定从那里做什么。

JSON 看起来像:

到目前为止我的镜头是这样的:

val hashtagsView = twitterEntitiesView >=> jsonObjectPL("hashtags") >=> jArrayPL

我也不确定 jArrayPL 是否正确。我想做的只是从数组中检索文本。

所以总结一下,谁能帮我找出如何构建一个镜头来查看主题标签,然后为数组的每个元素查看文本,最后得到一个值作为 JsonArray .

更新:

在 Travis 的帮助下,我编译了以下代码:

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))

不幸的是,我收到运行时错误:scalaz.Scalaz$.ToEitherOps(Ljava/lang/Object;)Lscalaz/syntax/EitherOps; 从行 val \/-(json) = Parse.parse(rawJSON)

开始

提前致谢!

您愿意使用 Argonaut 提供的 Monocle 镜头来代替 Scalaz 镜头吗?如果是这样,使用遍历会更好:

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)

然后:

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)"
    }
  ]
}

等等。您可以使用 Scalaz 镜头做类似的事情,但需要更多的工作。

好吧,如果您只想提取字段:

import argonaut._, Argonaut._
import scalaz._, Scalaz._

val doc = """{
  "hashtags": [
    { "indices": [0, 3], "text": "foo" },
    { "indices": [3, 6], "text": "bar" }
  ]
}"""

val \/-(json) = Parse.parse(doc)
val lense = jObjectPL
val hashtags = (lense >=> jsonObjectPL("hashtags") >=> jArrayPL).get(json)

hashtags.get.foreach(i => (lense >=> jsonObjectPL("indices") ).get(i).get.println )
hashtags.get.foreach(i => (lense >=> jsonObjectPL("text") ).get(i).get.println )

..或更好

val ind = ((v:Json) =>(lense >=> jsonObjectPL("indices") ).get(v).get)
val text = ((v:Json) =>(lense >=> jsonObjectPL("text") ).get(v).get)

hashtags.get.foreach(i => (ind(i), text(i)).println )