0

I would like to extract a slice of a JSON array using lenses, and get a Value back. More specifically, I am trying to do the following:

$ import qualified Data.ByteString.Lazy as LBS
$ import Data.Aeson.Lens
$ import Control.Lens
$ let e = "{\"headers\":[[\"Host\",\"localhost:9090\"],[\"Accept-Encoding\",\"gzip\"]]}" :: LBS.ByteString
$ e ^? key "headers" . nth 0 . _Array . sliced 0 2
$ Just [String "Host",String "localhost:9090"]

It works but I would like the result to be a Value and not a List. How can I "reconstruct" a JSON array as part of the lens expression?

insitu
  • 4,488
  • 3
  • 25
  • 42

1 Answers1

2

_Array is a Prism. This means you can invert it to get re _Array :: AsValue t => Getter (Vector Value) t.

e ^? key "headers" . nth 0 . _Array . sliced 0 2 . re _Array

You can also use over (or its alias (%~)):

e ^? key "headers" . nth 0 . to (over _Array (slice 0 2))
e ^? key "headers" . nth 0 . to (_Array %~ slice 0 2)
HTNW
  • 27,182
  • 1
  • 32
  • 60
  • `re _Array` adds `Contravariant f` to the context :( – insitu Aug 20 '18 at 18:03
  • the type of `%~` does not align correctly: Couldn't match type ‘vector-0.12.0.1:Data.Vector.Vector a0 -> f0 (vector-0.12.0.1:Data.Vector.Vector a0)’ with ‘vector-0.12.0.1:Data.Vector.Vector Value’` – insitu Aug 21 '18 at 06:48
  • I managed to get it working by adapting the type of the function, Thanks for the answer. – insitu Aug 21 '18 at 07:02