Reputation: 34884
I have such an ugly part of code:
request <- parseUrl "someUrl.com"
res <- withManager $ httpLbs request
case decode $ responseBody res :: Maybe Aeson.Value of
Just (Aeson.Object jsonObject) ->
case (HashMap.lookup "aaa" jsonObject) of
Just a ->
case a of
Aeson.Object jsonObject2 ->
case (HashMap.lookup "bbb" jsonObject2) of
Just b ->
case b of
Aeson.Object jsonObject3 ->
case (HashMap.lookup "ccc" jsonObject3) of
Just c ->
case c of
Array d ->
case (d ! 1) of
String a -> print a
_ -> error "error!!!"
_ -> error "error!!"
_ -> error "error!!"
_ -> error "error!!"
_ -> error "error!!"
_ -> error "error!!"
_ -> error "error!!"
_ -> error "Invalid JSON"
It does work well but it doesn't look good. How do I simplify it? I'm positive there is a way to do this. Note that I'm not using any custom data type for parsing a JSON and don't want to.
Upvotes: 3
Views: 263
Reputation: 1697
do
syntax for Maybe
monad:
request <- parseUrl "someUrl.com"
res <- withManager $ httpLbs request
let toPrint =
do Aeson.Object jsonObject <- decode $ responsBody res
Aeson.Object jsonObject2 <- HashMap.lookup "aaa" jsonObject
Aeson.Object jsonObject3 <- HashMap.lookup "bbb" jsonObject2
Array d <- HashMap.lookup "ccc" jsonObject3
String a <- return $ d ! 1
return a
case toPrint of
Just a -> print a
Nothing -> "Invalid JSON"
Upvotes: 5
Reputation: 74354
This problem—producing deep dives into large, complex data structures, is exactly what lens
seeks to solve. The idea of Lens
es isn't tough, but the package lens
can be scary. I've written a few tutorials on this concept, however, which may be useful
lens
to parse JSONlens
package in a Socratic style.In any case, for your particular example, we can replace this nested case with something like
print $ responseBody res ^!? key "aaa"
. key "bbb"
. key "ccc"
. ix 1
. _String
though I would recommend avoiding things like error
to indicate failure. The (^?)
combinators (also called preview
) would help.
Upvotes: 8