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

如何从字符串列表动态构建lens-aeson的path表达式?

动态构建lens-aeson路径表达式

我有如下Haskell代码,通过lens(lens-aeson)表达式读取JSON中的指定值:

import           Control.Lens    ((^?))
import           Data.Aeson      (Value)
import           Data.Aeson.Key  (fromString)
import           Data.Aeson.Lens (key)
import           Data.Text       (pack)

-- >>> readValue
-- Just (String "value")
readValue :: Maybe Value
readValue = json ^? path
  where
    path = key (fromString "key") . key (fromString "of") . key (fromString "interest")
    json = pack "{\"key\": {\"of\": {\"interest\": \"value\"}}}"

现在我希望通过传入配置列表["key","of","interest"]给readValue,动态构建其中的path表达式,请问该如何实现?


解决方案

核心思路是利用折叠操作将字符串列表转换为一系列key棱镜的组合,用函数组合符.串联成完整路径。

修改后的代码如下:

import           Control.Lens    ((^?), (.), id)
import           Data.Aeson      (Value, eitherDecode')
import           Data.Aeson.Key  (fromString)
import           Data.Aeson.Lens (key)
import           Data.Text       (pack)
import qualified Data.ByteString.Lazy.Char8 as BSL

-- >>> readValue ["key", "of", "interest"]
-- Just (String "value")
readValue :: [String] -> Maybe Value
readValue keys = case eitherDecode' (BSL.fromStrict . BSL.toStrict . pack $ jsonStr) of
  Right jsonVal -> jsonVal ^? buildPath keys
  Left _        -> Nothing
  where
    buildPath :: [String] -> Fold Value Value
    buildPath = foldl (\acc k -> acc . key (fromString k)) id
    jsonStr = "{\"key\": {\"of\": {\"interest\": \"value\"}}}"

关键细节:

  • buildPath函数通过foldl从左到右组合路径:初始值为id(恒等透镜),每一步将当前组合结果与新的key棱镜拼接。
  • 原代码中pack生成的Text需要转换为ByteString才能用eitherDecode'解析为Value类型;若你的JSON已经是Value实例,可直接跳过解码步骤。

简化版(假设输入已为Value):

readValue :: [String] -> Value -> Maybe Value
readValue keys json = json ^? foldl (\acc k -> acc . key (fromString k)) id keys

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:07:12