You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GHCI中便捷访问JSON字段,无需定义完整对应数据结构?

你遇到的类型错误本质是因为!运算符从Object中取出的值是Value类型,它可以是任意JSON类型(对象、数组、字符串、数字等),无法直接当做数组调用!!,也无法直接当做对象继续取值,必须先完成类型校验和转换。

方案1:使用lens-aeson实现类Python链式访问(推荐)

这种方式语法最简洁,和Python的链式访问体验最接近,不需要定义任何自定义数据类型:
首先需要引入依赖:aeson、lens-aeson,导入对应模块:

import Data.Aeson.Lens (key, nth, _String, _Array, _Object)
import Control.Lens ((^?), filtered)
import Data.Text (unpack)

提取ISBN的代码如下:

-- 安全取值,返回 Maybe String,任意节点缺失都会返回 Nothing
let isbn = body ^? key "items" 
                . nth 0 
                . key "volumeInfo" 
                . key "industryIdentifiers" 
                . _Array 
                . traverse 
                . _Object
                . filtered (\o -> o ^? key "type" . _String == Just "ISBN_10")
                . key "identifier" 
                . _String
                . fmap unpack

如果需要和你写的Python代码一样,找不到值就直接抛出异常,可以把^?替换为^?!。

方案2:使用aeson原生API手动解析(无额外依赖)

如果不想引入lens相关依赖,也可以直接用aeson自带的解析器组合实现,同样不需要定义完整JSON结构:

import Data.Aeson (withObject, withArray, withText, (.:), FromJSON(..))
import Data.Vector (toList, (!))
import Data.Either (either)
import Data.Text (unpack)

getISBN10 :: Object -> Maybe String
getISBN10 body = either (const Nothing) Just $ parseJSON isbnParser (Object body)
  where
    isbnParser = withObject "responseBody" $ \o -> do
      items <- o .: "items" >>= withArray "itemsList" pure
      firstItem <- parseJSON (items ! 0) >>= withObject "firstItem" pure
      volumeInfo <- firstItem .: "volumeInfo"
      identifiers <- volumeInfo .: "industryIdentifiers" >>= withArray "idList" (pure . toList)
      let findISBN [] = fail "ISBN_10 not found"
          findISBN (idVal:rest) = do
            idObj <- withObject "identifier" pure idVal
            idType <- idObj .: "type"
            if idType == "ISBN_10"
              then idObj .: "identifier" >>= withText "isbnVal" (pure . unpack)
              else findISBN rest
      findISBN identifiers

调用getISBN10 body即可得到Maybe String类型的ISBN结果。

生产环境建议优先使用返回Maybe的安全接口,避免因JSON结构变化导致程序崩溃。

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:36:02