2016-06-21 28 views
2

假设以下简单的JSON文件:如何使用argonaut镜头修改值并键入JSON?

 { 
     "key" : "val1" 
     } 

我想更新“键”的价值,但同时也改变它的类型,所以从字符串其更改为int。现在,使用HCURSOR像它下面是可能的,直截了当地做到这一点:

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

通过“撤销”上述位置我最终有一个新的JSON,其中的“钥匙”有一个数值,而不是一个String ,这是完美的。

使用镜头可以做同样的事吗?我试图做到以下几点:

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

不过,虽然我不明白这一点也不起作用错误,最后我结束了原来的JSON文档修改。如果我尊重数据类型,事情就像他们应该那样工作。是否有理由将镜头仅用于修改相同的数据类型?或者我只是在做一些非常错误的事情:)

回答

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} 

注意,由于镜头指向一个Json值,而不是JsonNumber,你必须包裹在JsonBigDecimaljNumber使类型排队。

+0

感谢您的快速回答@ Travis!非常感激。阅读镜头和Argonaut的文档我的印象是,您应该始终定义您所期望的那种JSON数据类型。但我想这是人类的一部分复杂的东西有时:) – cpard

+0

@cpard是的:)。在这种情况下,您希望在该位置使用JSON字符串,但是如果将'jStringPL'添加到镜头中,则无法更改该类型。 –