Scala:如何在 Monocle 中更新字段值

J P*_*lar 1 scala monocle-scala

鉴于monocle 项目中的JsonExample,我想创建一个镜头,其中 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
Run Code Online (Sandbox Code Playgroud)

我所追求的可能吗?
我也可以扩展它,如果年龄嵌套在另一个 JsObject 中,例如:

val n = (jsObject composeOptional index("nested") composePrism 
jsObject composeOptional index("age") composePrism jsNumber).set(45)
Run Code Online (Sandbox Code Playgroud)

在“嵌套”的键/值对尚不存在的情况下,它将在嵌套处创建对象,然后添加字段

n(JsObject(Map.empty)) -> JsObject(Map("nested" -> JsObject("age" -> JsNumber(45)))
Run Code Online (Sandbox Code Playgroud)

Jul*_*aut 5

让我们来看看indexat签名JsObject

def at(field: String): Lens[JsObject, Option[Json]]
def index(field: String): Optional[JsObject, Json]
Run Code Online (Sandbox Code Playgroud)

at是 aLens所以它的目标 ('Option[Json]') 总是存在的。这意味着,我们可以adddeleteupdateJson在的任何领域的元素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 = {}
Run Code Online (Sandbox Code Playgroud)

另一方面,indexis an Optionalso it is target ( Json) 可能存在也可能不存在。这意味着indexcan only updatevalues 但不能adddelete

(jObjectPrism composeLens index("name")).set(jString("Robert"))(Json())
> res3: argonaut.Json = {}

(jObjectPrism composeLens index("name")).set(jString("Robert"))(res0)
> res4: argonaut.Json = {"name":"Robert"}
Run Code Online (Sandbox Code Playgroud)

因此,回到您最初的问题,如果您想在特定字段中使用addupdate赋值,您需要使用 aat并将其包装JsonSome(请参阅res1)中,它将覆盖或创建该Json字段。