[英]How to inspect parsed Aeson Value?
如何瀏覽大Aeson
Values
? 我知道應該有一個我感興趣的字符串嵌套在結構中的某個位置。 我如何找到它?
到目前為止,我只知道如何查詢構造函數,發現它是一個數組。 我怎么能比這更深入?
> take 20 $ show bt
"Array (fromList [Obj"
lens
軟件包具有有用的功能,可用於檢查類似JSON Value
的樹狀結構。 還有lens-aeson
包,帶有額外的JSON特定功能。
import Data.Text
import Data.Aeson
import Data.Aeson.Lens (_Value,_String) -- this is from lens-aeson
import Data.Foldable (toList)
import Control.Lens (Fold,folding,universeOf,toListOf,paraOf,preview)
我們可以從定義鏡頭Fold
開始,該鏡頭Fold
提取給定JSON Value
的直接子Values
:
vchildren :: Fold Value Value
vchildren = folding $ \v -> case v of
Object o -> toList o
Array a -> toList a
_ -> []
folding
是lens
創建的功能,而Fold
是返回列表的功能。 在我們的例子中,是Value
的列表。
我們可以將vchildren
與Control.Lens.Plated
的universeOf
函數結合使用,以獲取提取Value
所有傳遞后代(包括其自身)的函數:
allValues :: Value -> [Value]
allValues = universeOf vchildren
並且此函數提取Value
中包含的所有文本。 它使用_String
從棱鏡Data.Aeson.Lens
(一個Prism
是有點像可以被傳遞了“具體化”模式):
allTexts :: Value -> [Text]
allTexts = toListOf (folding allValues . _String)
Control.Lens.Plated
還具有諸如paraOf
類的有趣功能,可用於構建“ paramorphims”。 亞同態是從葉子開始的樹狀結構的“受控破壞”,並向上構建結果。 例如這個功能
vpara :: (Value -> [r] -> r) -> Value -> r
vpara = paraOf vchildren
將另一個函數作為其第一個參數,該函數接收“當前節點”以及下面節點的中間結果,並構建當前節點的中間結果。
vpara
將開始從葉子中使用JSON值(這些節點的中間結果列表只是[]
)並向上進行。
vpara
一種可能用法是獲取JSON中路徑的列表,該列表以匹配某些條件的文本結尾,如下所示:
type Path = [Value]
pathsThatEndInText :: (Text -> Bool) -> Value -> [Path]
pathsThatEndInText pred = vpara func
where
func :: Value -> [[Path]] -> [Path]
func v@(String txt) _ | pred txt = [[v]]
func v l@(_:_) = Prelude.map (v:) (Prelude.concat l)
func _ _ = []
為了獲得由pathsThatEndInText
返回的路徑之一的某種可讀性描述:
import qualified Data.HashMap.Strict as HM
import qualified Data.Vector as V
describePath :: Path -> [String]
describePath (v:vs) = Prelude.zipWith step (v:vs) vs
where
step (Object o) next = (unpack . Prelude.head . HM.keys . HM.filter (==next)) o
step (Array a) next = (show . maybe (error "not found") id) (V.elemIndex next a)
step _ _ = error "should not happen"
最后,這是一個示例JSON值,用於在ghci中測試上述功能:
exampleJSON :: Value
exampleJSON = maybe Null id (preview _Value str)
where
str = "[{ \"k1\" : \"aaa\" },{ \"k2\" : \"ccc\" }, { \"k3\" : \"ddd\" }]"
這就是要點 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.