鉴于单片眼镜项目中的JsonExample,我想创建一个镜头,其中set set将替换键/值对中的值,或者如果它不存在则创建键/值对
然而,这似乎用索引(可以组成类型安全)或者at表示,它不是安全类型
//for replacing:
(jsObject composeOptional index("age") composePrism jsNumber).set(45)
//for creating:
(jsObject composeLens at("age")).set(JsNumber(45)) <- will accept any old json
我可以追求的是什么? 我也可以扩展它,如果年龄嵌套在另一个JsObject中,例如:
val n = (jsObject composeOptional index("nested") composePrism
jsObject composeOptional index("age") composePrism jsNumber).set(45)
&#34;嵌套&#34;的键/值对还没有存在,它会在嵌套时创建对象,然后添加字段
n(JsObject(Map.empty)) -> JsObject(Map("nested" -> JsObject("age" -> JsNumber(45)))
答案 0 :(得分:4)
让我们看一下index
的{{1}}和at
签名:
JsObject
def at(field: String): Lens[JsObject, Option[Json]]
def index(field: String): Optional[JsObject, Json]
是at
,因此其目标('Option [Json]')始终存在。这意味着我们可以在Lens
的任意字段add
,delete
和update
Json
元素。
JsonObject
另一方面,import argonaut._, Argonaut._
import monocle.function._
(jObjectPrism composeLens at("name")).set(Some(jString("John")))(Json())
> res0: argonaut.Json = {"name":"John"}
(jObjectPrism composeLens at("name")).set(Some(jString("Robert")))(res0)
> res1: argonaut.Json = {"name":"Robert"}
(jObjectPrism composeLens at("name")).set(None)(res0)
> res2: argonaut.Json = {}
是index
,因此目标(Optional
)可能存在也可能不存在。这意味着Json
只能index
个值,但不能update
或add
。
delete
回到原来的问题,如果您想在特定字段中输入(jObjectPrism composeLens index("name")).set(jString("Robert"))(Json())
> res3: argonaut.Json = {}
(jObjectPrism composeLens index("name")).set(jString("Robert"))(res0)
> res4: argonaut.Json = {"name":"Robert"}
或add
,则需要使用update
并打包at
在Json
(请参阅Some
)中,它会在该字段覆盖或创建res1
。
答案 1 :(得分:3)
目前图书馆里有specific behaviour。
当您使用Optional
或Iso
撰写Prism
时,它会将右侧参数降级为POptional
而且这很麻烦。
Iso[A,B]
和Prism[A,B]
与Lens[A,B]
和Optional[A,B]
的区别在于reverseGet
可以完全从{{1}创建A
的元素} B
需要原始值set
因此,当A
和Optional
完全合法时,您无法修改部分值,而在orignal Lens
或Map
中没有此值JsObject
和Iso
您可以定义另一种行为。
在等待讨论the issue时,您可以使用以下解决方法
Prism
现在您可以尝试将代码更改为
implicit class POptStrictComposition[S, T, A, B](self: POptional[S, T, A, B]) {
def sComposePrism[C, D](other: PPrism[A, B, C, D]) = new POptional[S, T, C, D] {
def getOrModify(s: S): T \/ C =
self.getOrModify(s).flatMap(a => other.getOrModify(a).bimap(self.set(_)(s), identity))
def set(d: D): S => T =
self.set(other.reverseGet(d))
def getOption(s: S): Option[C] =
self.getOption(s) flatMap other.getOption
def modifyF[F[_] : Applicative](f: C => F[D])(s: S): F[T] =
self.modifyF(other.modifyF(f))(s)
def modify(f: C => D): S => T =
self.modify(other.modify(f))
}
def ^!<-?[C, D](o: PPrism[A, B, C, D]) = sComposePrism(o)
def sComposeIso[C, D](other: PIso[A, B, C, D]) = sComposePrism(other.asPrism)
def ^!<->[C, D](o: PIso[A, B, C, D]) = sComposeIso(o)
}
并报告是否有帮助