解析JSON中的嵌套值

解析JSON中的嵌套值,json,haskell,Json,Haskell,我的代码有这么一个丑陋的部分: 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 -&

我的代码有这么一个丑陋的部分:

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"
请求
案例a
Aeson.Object JSONObject 2->
的案例(HashMap.lookup“bbb”jsonObject2)
只是b->
案件b
Aeson.Object JSONObject 3->
案例(HashMap.lookup“ccc”jsonObject3)
只是c->
案例c
数组d->
第(d!1)款
字符串a->打印a
_->错误“错误!!!”
_->错误“错误!!”
_->错误“错误!!”
_->错误“错误!!”
_->错误“错误!!”
_->错误“错误!!”
_->错误“错误!!”
_->错误“无效JSON”
它确实很管用,但看起来不太好。我如何简化它?我肯定有办法做到这一点。
请注意,我没有使用任何自定义数据类型来解析JSON,我不想这样做

深入研究大型复杂数据结构的问题正是
lens
寻求解决的问题。
Lens
es的想法并不难,但是包
Lens
可能会让人害怕。然而,我已经写了一些关于这个概念的教程,这可能会很有用

  • 提供了一个使用
    lens
    解析JSON的示例
  • 以苏格拉底式的风格贯穿整个
    镜头
在任何情况下,对于您的特定示例,我们都可以用以下内容替换这个嵌套的case

print $ responseBody res ^!? key "aaa" 
                         .   key "bbb"
                         .   key "ccc"
                         .   ix 1 
                         .   _String

尽管我建议避免像
error
这样表示失败的事情。
(^?
组合符(也称为
预览
)会有所帮助。

do
语法对于
可能
单子:

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"

请求我认为
do
的最后一行可以是
let(字符串a)=d!1
而不是通过一个
可能
循环它。这里我们特别希望在模式不匹配时调用
fail
函数。所以,
return
就是这样。