gpt4 book ai didi

json - Play JSON : turn a Seq[Reads[JsObject]] into one Reads[JsObject]

转载 作者:行者123 更新时间:2023-12-01 13:44:43 26 4
gpt4 key购买 nike

我动态生成一堆Reads[JsObject]然后我在 Seq[Reads[JsObject]] .为了实际应用所有这些单Reads[JsObject] ,我必须将它们与 and 合并合二为一Reads[JsObject] .这可能吗?

我有(示例):

val generatedReads: Seq[Reads[JsObject]] = Seq(
(__ \ "attr1").json.copyFrom((__ \ "attr1" \ "attr1a").json.pick),
(__ \ "attr2").json.pickBranch
)

我需要的:
val finalReads: Reads[JsObject] =
(__ \ "attr1").json.copyFrom((__ \ "attr1" \ "attr1a").json.pick) and
(__ \ "attr2").json.pickBranch

编译时不知道要选择的属性名称和分支,这就是它必须是动态的原因。

最佳答案

这是一个相当普遍的问题。这个答案的灵感来自 Reads.traversableReads[F[_], A] .

支持 Reads[A] 累积的想法,我们必须尝试所有您生成的Reads[JsObject]为此,我们将使用Either[Errors, Vector[JsObject]]。在原始 'Reads.traversableReads[F[_], A]' 中返回 Reads[List[A]]或者一些集合,但是我们需要简单的Json,没问题,++连接我们的 JsObjects .

def reduceReads(generated: Seq[Reads[JsObject]]) = Reads {json =>
type Errors = Seq[(JsPath, Seq[ValidationError])]

def locate(e: Errors, idx: Int) = e.map { case (p, valerr) => (JsPath(idx)) ++ p -> valerr }

generated.iterator.zipWithIndex.foldLeft(Right(Vector.empty): Either[Errors, Vector[JsObject]]) {
case (acc, (r, idx)) => (acc, r.reads(json)) match {
case (Right(vs), JsSuccess(v, _)) => Right(vs :+ v)
case (Right(_), JsError(e)) => Left(locate(e, idx))
case (Left(e), _: JsSuccess[_]) => Left(e)
case (Left(e1), JsError(e2)) => Left(e1 ++ locate(e2, idx))
}
}
.fold(JsError.apply, { res =>
JsSuccess(res.fold(Json.obj())(_ ++ _))
})
}

scala> json: play.api.libs.json.JsValue = {"attr1":{"attr1a":"attr1a"},"attr2":"attr2"}

scala> res7: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"attr1":"attr1a","attr2":"attr2"},)

新的很棒的简单答案

几天后,我有了这个绝妙的主意。 object Reads有隐含 Reducer[JsObject, JsObject]所以我们可以减少 Seq(Reads[JsObject])FunctionalBuilder ( and 然后是 reduce )!
def reduceReads(generated: Seq[Reads[JsObject]]) = 
generated.foldLeft(Reads.pure(Json.obj())){
case (acc, r) =>
(acc and r).reduce
}

这个解决方案简单明了。基于原创想法 Seq(Reads[JsObject]) => Seq(JsResult[JsObject]) => Reads[JsObject]映射,但最后一个基于基本的 Json 组合器原则 Seq(Reads[JsObject]) => Reads[JsObject]
总的来说,问题解决了,但任务本身并不正确。如果你不控制 Reads,你想看看同一个路径是否会被使用两次?

关于json - Play JSON : turn a Seq[Reads[JsObject]] into one Reads[JsObject],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36849032/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com