2015-12-29 31 views
10

我竭力要弄清楚一個問題與埃宋鏡頭操縱JSON。我的任務就像在JSON中添加一個鍵到嵌套對象一樣簡單。我能夠改變現有keyby手段:使用鏡頭添加鍵和值的嵌套地圖

> :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}}" 

當然,這是我做的有什麼不對,但是我想我已經沒有法力去理解究竟是什麼了。

勞駕點我在正確的方向?

謝謝!

回答

15

正如dfeuer指出的那樣,at可以插入到地圖中,而keyix只是遍歷元素(如果存在)。我們可以做到以下幾點:

> "{ \"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" 
+0

感謝您爲我的案例和附加說明提供一個可行的示例! – SkyWriter

3

key基於ix,其文檔表明它不夠強大,無法做到您想要的並指向Control.Lens.At.at。我很確定,應該爲你做詭計。其基本思想是,你先從_Object棱鏡打開JSON文本轉換爲對象,然後使用at key得到一個鏡頭到該字段Maybe。然後您可以將其更改爲Just您想要的。

這將很好地工作,只要沿着你想借此存在路徑中的所有對象。如果你想(可能)從零開始並創建一個單字段對象鏈,你可能會發現更令人討厭的事情。幸運的是,你可能不需要這樣做。

+0

感謝您指出的原因'key'不適合我的情況下工作。我真的試圖查看源代碼,但它更加不合理:-)猜測需要時間來解決這個問題。 – SkyWriter

+0

@SkyWriter,如果你熟悉模型/視圖的術語,你可以認爲_Object'的'作爲提供'Text'模型的完整'Object'「視圖」,但只有當'Text'成功地解析爲'Object'。假設視圖成功,您可以通過該視圖檢查和修改「文本」模型。 – dfeuer