module Data.Aeson.Transform ( -- * Example usage -- $use -- * Transformations Builder , at , attr , keep , Data.Aeson.Transform.map , Data.Aeson.Transform.index , atIndex , obj , merge ) where import Data.Aeson as A import Data.Text import qualified Data.Vector as Vec import qualified Data.HashMap.Strict as H type Builder = Value -> Value -- | Move to value in current object at :: Text -> Builder -> Builder at k b (A.Object o) = b (o H.! k) at _ _ _ = error "Expecting object (at)" -- | Get value in current object attr :: Text -> Builder attr k (A.Object o) = o H.! k attr _ _ = error "Expecting object (attr)" -- | Filter current object by keys keep :: [Text] -> Builder keep ks (A.Object o) = A.Object $ H.filterWithKey (const . (`elem` ks)) o keep _ _ = error "Expecting object (keep)" -- | Map over input array map :: Builder -> Builder map b (Array a) = Array $ Vec.map b a map _ _ = error "Expecting array (map)" -- | Get value at index of current array index :: Int -> Builder index i (Array a) = a Vec.! i index _ _ = error "Expecting array (index)" -- | Move to index in current array atIndex :: Int -> Builder -> Builder atIndex i b (Array a) = b $ a Vec.! i atIndex _ _ _ = error "Expecting array (atIndex)" -- | Produce object with given keys obj :: H.HashMap Text Builder -> Builder obj h x = A.Object $ H.map (\b -> b x) h -- | Combine two objects merge :: Builder -> Builder -> Builder merge a b val = case (a val, b val) of (Object c, Object d) -> Object $ H.union c d _ -> error "Expected two objects (merge)" -- $use -- -- Filter unwanted attributes from an object -- -- > keep ["nice", "good"] -- > -- > -- { bad: 3, good: 1, nice: 500, evil: -3 } -- > -- => { good: 1, nice: 500 } -- -- Grab value -- -- > attr "foo" -- > -- > -- { foo: 2 } => 2 -- -- Dig deeper -- -- > at "foo" $ attr "bar" -- > -- > -- { foo: { bar: 3 }} => 3 -- -- Map stuff -- -- > map $ attr "foo" -- > -- > -- [{ foo:1 }, { foo:2 }] => [1, 2] -- -- Extract indices -- -- > map $ index 0 -- > -- > -- [[1,2], [3,4]] => [1, 3] -- -- Create object -- -- > obj $ fromList [ -- > ("first", index 0) -- > , ("second", index 1) -- > ] -- > -- > -- ["hi", "bye"] => { first:"hi", second:"bye" } -- -- Transform position -- -- > at "ranks" $ atIndex 0 $ attr "name" -- > -- > -- {ranks: [ { name:"winner", score:12 }, { name:"loser", score: 3 ]} -- > -- => "winner" -- -- Combine objects -- -- > merge (attr "foo") (attr "bar") -- > -- > -- { foo: { a:1, b:2 }, bar: { b:3, c:4 } } -- > -- => { a:1, b:2, c:4 }