I like to think of Aeson as happening in two distinct steps, the parsing from ByteString -> Value
and the mapping from FromJSON a => Value -> a
. If you don't immediately know what the correct mapping is you can simply parse to a Value
as you've done. Later at runtime when you decide the proper mapping you can do that later.
import qualified Data.HashMap.Strict as Hm
decodeResponse :: ByteString -> Either String Value
decodeResponse bs = do
val <- eitherDecode bs
case val of
Object o -> case Hm.lookup "response" o of
Nothing -> fail "Invalid structure, missing 'response' key"
Just resp -> return resp
_ -> fail "Invalid structure, expected an object"
To perform a mapping without a parse, to convert a Value
to a FromJSON a => a
, you use the parse
/parseEither
/parseMaybe
family and run the parser generated by parseJSON
mapValue :: FromJSON a => Value -> Either String a
mapValue = parseString parseJSON