2

假设以下简单的 JSON 文档:

       {
         "key" : "val1"
       }

我想更新“key”的值,但同时也改变它的类型,所以从字符串改变它到一个int。现在,使用像下面这样的 HCursor 是可能的,而且很直接:

 val cursor = js.hcursor
 val position = (cursor --\ "key") >-> (_ => jNumber(1))

通过“撤消”上述位置,我最终得到了一个新的 json,其中“key”具有数值而不是字符串,这是完美的。

是否可以使用镜头做同样的事情?我尝试执行以下操作:

val lense = jObjectPL >=>
          jsonObjectPL("key") >=>
          jNumberPL
lense.mod(_ => JsonBigDecimal(1), js)

但是,尽管我没有收到错误,但它也不起作用,最后我得到了未修改的原始 json 文档。不过,如果我尊重数据类型,事情就会按应有的方式工作。是否有理由仅将镜头用于相同数据类型的修改?或者我只是在做一些非常错误的事情:)

4

1 回答 1

4

不,没有什么大错——你快到了。问题是这条路径:

jObjectPL >=> jsonObjectPL("key") >=> jNumberPL

导航到位于 的 JSON 编号"key"。您js的键没有 JSON 编号,因此镜头不指向任何内容,修改不会影响任何内容。

您只需从镜头中移除最后一步即可解决此问题:

val lens = jObjectPL >=> jsonObjectPL("key")

这只是导航到该"key"字段,但不会限制它是哪种 JSON 值。然后,您可以将其更改为您想要的任何内容:

scala> val lens = jObjectPL >=> jsonObjectPL("key")
lens: scalaz.PLensFamily[...

scala> lens.mod(_ => jNumber(JsonBigDecimal(1)), js)
res0: argonaut.Json = {"key":1}

请注意,由于 lens 指向一个Json值,而不是 a JsonNumber,因此您必须将 in 包装起来JsonBigDecimaljNumber使类型对齐。

于 2016-06-21T18:13:15.547 回答