如何使用 argonaut lens 修改 JSON 的值和类型?
How to modify value and type in JSON using argonaut lens?
假设以下简单 JSON 文档:
{
"key" : "val1"
}
我想更新 "key" 的值,但同时也更改其类型,因此将其从字符串更改为 int。现在,使用像下面这样的 HCursor 就可以直接做到:
val cursor = js.hcursor
val position = (cursor --\ "key") >-> (_ => jNumber(1))
通过 "undoing" 上面的位置我最终得到一个新的 json 其中 "key" 有一个数值而不是一个字符串,这是完美的。
是否可以使用镜头来做同样的事情?我尝试执行以下操作:
val lense = jObjectPL >=>
jsonObjectPL("key") >=>
jNumberPL
lense.mod(_ => JsonBigDecimal(1), js)
但是虽然我没有收到错误,但它也不起作用,最后我得到了未修改的原始 json 文档。不过,如果我尊重数据类型,事情就会按预期进行。是否有理由将镜头仅用于修改相同的数据类型?或者我只是做了一些非常错误的事情:)
不,没有什么大错——你快完成了。问题是这条路径:
jObjectPL >=> jsonObjectPL("key") >=> jNumberPL
导航到 "key"
的 JSON 号码。你的 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}
请注意,由于镜头指向的是 Json
值,而不是 JsonNumber
,因此您必须将 JsonBigDecimal
包裹在 jNumber
中才能使类型排队。
假设以下简单 JSON 文档:
{
"key" : "val1"
}
我想更新 "key" 的值,但同时也更改其类型,因此将其从字符串更改为 int。现在,使用像下面这样的 HCursor 就可以直接做到:
val cursor = js.hcursor
val position = (cursor --\ "key") >-> (_ => jNumber(1))
通过 "undoing" 上面的位置我最终得到一个新的 json 其中 "key" 有一个数值而不是一个字符串,这是完美的。
是否可以使用镜头来做同样的事情?我尝试执行以下操作:
val lense = jObjectPL >=>
jsonObjectPL("key") >=>
jNumberPL
lense.mod(_ => JsonBigDecimal(1), js)
但是虽然我没有收到错误,但它也不起作用,最后我得到了未修改的原始 json 文档。不过,如果我尊重数据类型,事情就会按预期进行。是否有理由将镜头仅用于修改相同的数据类型?或者我只是做了一些非常错误的事情:)
不,没有什么大错——你快完成了。问题是这条路径:
jObjectPL >=> jsonObjectPL("key") >=> jNumberPL
导航到 "key"
的 JSON 号码。你的 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}
请注意,由于镜头指向的是 Json
值,而不是 JsonNumber
,因此您必须将 JsonBigDecimal
包裹在 jNumber
中才能使类型排队。