我很难通过Argonaut文档,所以我想我只想问一个简单的例子。
val input = """{"a":[{"b":4},{"b":5}]}"""
val output = ??? // desired value: List(4, 5)
我可以将光标移到数组:
Parse.parse(input).map((jObjectPL >=> jsonObjectPL("a") >=> jArrayPL)(_))
// scalaz.\/[String,Option[scalaz.IndexedStore[argonaut.Argonaut.JsonArray,
// argonaut.Argonaut.JsonArray,argonaut.Json]]] =
// \/-(Some(IndexedStoreT((<function1>,List({"b":4}, {"b":5})))))
但那又怎么样?我是在正确的轨道上吗?我是否应该为此使用游标?
编辑 - 我想这是一些进展。我为列表写了一个解码器:
Parse.parse("""[{"b": 4}, {"b": 5}]""")
.map(_.as(IListDecodeJson(DecodeJson(_.downField("b").as[Int]))))
// scalaz.\/[String,argonaut.DecodeResult[scalaz.IList[Int]]] =
// \/-(DecodeResult(\/-([4,5])))
编辑 - 慢慢开始把它放在一起......
Parse.parse(input).map(_.as[HCursor].flatMap(_.downField("a").as(
IListDecodeJson(DecodeJson(_.downField("b").as[Int])))))
// scalaz.\/[String,argonaut.DecodeResult[scalaz.IList[Int]]] =
// \/-(DecodeResult(\/-([4,5])))
编辑 - 所以我想到目前为止我的最佳解决方案是:
Parse.parse(input).map(_.as(
DecodeJson(_.downField("a").as(
IListDecodeJson(DecodeJson(_.downField("b").as[Int])).map(_.toList)
))
))
感觉有点冗长。
答案 0 :(得分:9)
你可以很好地利用Argonaut中的新Monocle支持(我在这里使用Argonaut master,因为6.1里程碑仍在Monocle 0.5上):
import argonaut._, Argonaut._
import scalaz._, Scalaz._
import monocle._, Monocle._
val lens =
Parse.parseOptional ^<-?
jObjectPrism ^|-?
index("a") ^<-?
jArrayPrism ^|->>
each ^<-?
jObjectPrism ^|-?
index("b") ^<-?
jIntPrism
然后:
scala> lens.getAll("""{"a":[{"b":4},{"b":5}]}""")
res0: scalaz.IList[Int] = [4,5]
操作员起初看起来很可怕,但是你已经习惯了它们,并且组合的部分很自然地阅读。当然,由于这是一个镜头,除了getAll
之外,还可以使用各种操作。
答案 1 :(得分:0)
这种案例分类可能不是您想要的方式,但这是我的2美分。
case class B(b: Int)
object B {
implicit def BCodecJson: CodecJson[B] =
casecodec1(B.apply, B.unapply)("b")
}
val jsonString = """{"a":[{"b":4},{"b":5}]}"""
val vals: List[Int] = Parse.parseOption(jsonString).map { json: Json =>
(json -|| List("a")).flatMap(_.as[List[B]].value).getOrElse(Nil).map(_.b)
}.getOrElse(Nil)
我想是的。