首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Argonaut在JSON数组上进行映射

使用Argonaut在JSON数组上进行映射
EN

Stack Overflow用户
提问于 2015-03-21 14:25:09
回答 2查看 1.4K关注 0票数 4

我在艰难地阅读Argonaut文档时遇到了困难,所以我想我只需要一个简单的例子。

代码语言:javascript
复制
val input = """{"a":[{"b":4},{"b":5}]}"""

val output = ??? // desired value: List(4, 5)

我可以将光标移到数组中:

代码语言:javascript
复制
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})))))

但是然后呢?我在正确的轨道上吗?我应该为此使用游标吗?

编辑--我想,这是一些进展。我为这个列表写了一个解码器:

代码语言:javascript
复制
Parse.parse("""[{"b": 4}, {"b": 5}]""")
  .map(_.as(IListDecodeJson(DecodeJson(_.downField("b").as[Int]))))
// scalaz.\/[String,argonaut.DecodeResult[scalaz.IList[Int]]] =
// \/-(DecodeResult(\/-([4,5])))

编辑-慢慢地开始把它放在一起...

代码语言:javascript
复制
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])))

编辑-所以我想到目前为止我最好的解决方案是:

代码语言:javascript
复制
Parse.parse(input).map(_.as(
  DecodeJson(_.downField("a").as(
    IListDecodeJson(DecodeJson(_.downField("b").as[Int])).map(_.toList)
  ))
))

不过,感觉有点冗长。

EN

回答 2

Stack Overflow用户

发布于 2015-03-22 07:03:18

你可以很好地使用are中的新的Monocle支持(我在这里使用的是are master,因为6.1里程碑仍然在Monocle0.5上):

代码语言:javascript
复制
import argonaut._, Argonaut._
import scalaz._, Scalaz._
import monocle._, Monocle._

val lens =
  Parse.parseOptional ^<-? 
  jObjectPrism        ^|-?
  index("a")          ^<-?
  jArrayPrism         ^|->>
  each                ^<-?
  jObjectPrism        ^|-?
  index("b")          ^<-?
  jIntPrism

然后:

代码语言:javascript
复制
scala> lens.getAll("""{"a":[{"b":4},{"b":5}]}""")
res0: scalaz.IList[Int] = [4,5]

操作符一开始看起来很可怕,但你会习惯它们,而且组成的代码读起来也很自然。当然,由于这是一个镜头,除了getAll之外,你还可以使用所有类型的操作。

票数 9
EN

Stack Overflow用户

发布于 2015-10-22 20:09:44

这种案例分类可能不是你想要的方式,但这是我的2点意见。

代码语言:javascript
复制
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)

我想这就够了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29179897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档