Использование объектива для добавления ключа и значения в вложенную карту
Я изо всех сил пытаюсь разобраться с проблемой манипулирования JSON объективами Aeson. Моя задача так же просто, как добавить ключ к вложенному объекту в 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}}"
Конечно, это я делаю что-то неправильно, но я полагаю, что я не в мане, чтобы понять, что именно.
Не могли бы вы указать мне в правильном направлении?
Спасибо!
Ответы
Ответ 1
Как отметил 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"
Ответ 2
key
основан на ix
, документация которого указывает, что он недостаточно мощный, чтобы делать то, что вы хотите, и указывает на Control.Lens.At.at
. Я почти уверен, что должен сделать трюк для вас. Основная идея заключается в том, что вы начинаете с призмы _Object
, чтобы превратить текст JSON в объект, а затем используйте at key
, чтобы получить объектив в этом поле как Maybe
. Затем вы можете изменить его на Just
, что вы хотите.
Это будет работать очень хорошо, если все объекты вдоль пути, который вы хотите использовать, существуют. Если вы хотите (потенциально) начать с нуля и создать цепочку однопольных объектов, вы, скорее всего, найдете вещи более раздражающими. К счастью, вам, вероятно, не нужно это делать.