如何从字符串列表动态构建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
相关产品推荐
相关产品推荐

