首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为给定的Seq[T]编写读( Reads[T] )?

如何为给定的Seq[T]编写读( Reads[T] )?
EN

Stack Overflow用户
提问于 2014-06-12 18:38:30
回答 1查看 626关注 0票数 0

我正在使用play框架2.2.3版本的json库。我有以下json对象:

代码语言:javascript
复制
{
    "myData":
    [
        {
            "A": "some text",
            "B": [10, 20, 30]
        },
        {
            "A": "some other text",
            "B": [15, 25, 35]
        },
        ...
    ]
}

我想将这个json对象反序列化为一个Vector[Map[String, Vector[Int]]]。因此,结果应该是:

代码语言:javascript
复制
Vector(Map("some text" -> Vector(10, 20, 30)), Map("some other text" -> Vector(15, 25, 35)))

当我试图实现这一目标时,我能够编写一个Reads[Map[String, Vector[Int]]],用于单个条目。

代码语言:javascript
复制
import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val singleEntryReads: Reads[Map[String, Vector[Int]]] = {
  (__).read(
    (__ \ "A").read[String] and
    (__ \ "B").read[Vector[Int]] tupled) map { keyAndValue =>
      val (a, b) = keyAndValue
      Map(a -> b)
    }
}

因此,转换适用于单个条目:

代码语言:javascript
复制
scala> (myJsonObject \ "myData")(0).validate[Map[String, Vector[Int]]]     
res: play.api.libs.json.JsResult[Map[String, Vector[Int]]] = JsSuccess(Map(some text -> Vector(10, 20, 30)))

但是我怎么写Reads[Vector[Map[String, Vector[Int]]]]呢?我最好的想法是这样做,类似于给this older question的答案

代码语言:javascript
复制
implicit val allEntriesReads: Reads[Seq[Map[String, Vector[Int]]]] = Reads.seq(singleEntryReads)

我试着像这样用它:

代码语言:javascript
复制
scala> (myJsonObject \ "myData").validate[Seq[Map[String, Vector[Int]]]]"
res2: play.api.libs.json.JsResult[Seq[Map[String, Vector[Int]]]] = JsError(List(((147)/B,List(ValidationError(error.path.missing,WrappedArray()))), ((148)/B,List(ValidationError(error.path.missing,WrappedArray())))))

但这不起作用,给了我一个JsError()。我必须如何实现第二个Reads才能使它以这种方式工作?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-12 19:43:09

你不需要这么做。玩!它附带了一个隐式(在Reads同伴对象中定义的),它已经完成了您想要的任务:

代码语言:javascript
复制
implicit def traversableReads[F[_], A](implicit bf: CanBuildFrom[F[_], A, F[A]], ra: Reads[A]): Reads[F[A]]

如果对序列类型有隐式Reads[A]和适当的CanBuildFrom (标准库集合类型(例如Vector)已经存在这些类型),则该隐式Reads[F[A]]将充当隐式Reads[F[A]],其中F是集合类型。

Scala允许您定义一个本身带有隐式参数的implicit def,它将充当其返回类型的隐式值。使用implicit def时,Scala将在调用站点搜索隐式参数。所以:

代码语言:javascript
复制
.validate[Seq[Map[String, Vector[Int]]]]

变成:

代码语言:javascript
复制
.validate[Seq[Map[String, Vector[Int]]]](traversableReads)

然后变成:

代码语言:javascript
复制
.validate[Seq[Map[String, Vector[Int]]]](traversableReads(singleEntryReads, Seq.canBuildFrom)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24191640

复制
相关文章

相似问题

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