我正在努力解决使用Aeson镜头操纵JSON的问题。我的任务就像在JSON中向嵌套对象添加密钥一样简单。我能够通过以下方式更改现有密钥:
> :set -XOverloadedStrings
> import Control.Lens
> import Data.Aeson
> import Data.Aeson.Lens
> "{ \"a\": { \"b\": 10 } }" & key "a" . key "b" .~ String "jee"
"{\"a\":{\"b\":\"jee\"}}"
但是当我尝试让它处理新密钥时,它只是默默地无法添加它:
> "{ \"a\": { \"b\": 10 } }" & key "a" . key "c" .~ String "jee"
"{\"a\":{\"b\":10}}"
当然,这是我做错了什么,但我认为我已经达不到法术力量。
请您指出我正确的方向吗?
谢谢!
答案 0 :(得分:17)
正如dfeuer所指出的,at
可以插入到地图中,而key
和ix
只会遍历元素(如果存在)。我们可以做到以下几点:
> "{ \"a\": { \"b\": 10 } }" & key "a" . _Object . at "c" ?~ String "foo"
"{\"a\":{\"b\":10,\"c\":\"foo\"}}
at
是专注于Maybe element
- s的镜头,我们可以通过设置为Just
某个元素来插入,并通过设置为Nothing
来删除。 at "c" ?~ String "foo"
与at "c" .~ Just (String "foo")
相同。
如果我们想要嵌套插入,我们可以使用non
来定义要插入的默认值:
> "{ \"a\": { \"b\": 10 } }" & key "a" . _Object . at "c" . non (Object mempty) . _Object . at "d" ?~ String "foo"
"{\"a\":{\"b\":10,\"c\":{\"d\":\"foo\"}}}"
这是一个满口的,所以我们可以考虑一些部分:
> let atKey k = _Object . at k
> "{ \"a\": { \"b\": 10 } }" & key "a" . atKey "c" . non (Object mempty) . atKey "d" ?~ String "foo"
答案 1 :(得分:3)
ix
基于Control.Lens.At.at
,其文档表明它不足以执行您想要的操作并指向_Object
。我很确定应该为你做的伎俩。基本的想法是,您从at key
棱镜开始将JSON文本转换为对象,然后使用Maybe
将镜头作为Just
>进入该字段 EM>。然后,您可以将其更改为{{1}}您想要的内容。
只要您想要采用的路径上的所有对象都存在,这将非常有效。如果你想(可能)从零开始并创建一个单场对象链,你可能会发现更烦人的事情。幸运的是,你可能不需要这样做。