我有以下一些代码,我对它不满意:
import Data.Aeson.Lens
import Data.Aeson.Types
import Data.Text hiding (foldl, map)
path :: (Applicative f, AsValue t) => [Text] -> (Value -> f Value) -> t -> f t
path [] = error "No path provided"
path (i:is) = foldl (.) (key i) (map key is)
path
意味着成为嵌套JSON对象的镜头。例如:
"{ \"a\": { \"b\": 8} }" ^? path ["a", "b"] == Just (Number 8.0)
目前这有效,但有些明显的缺点是功能不完全。
我尝试了以下定义:
path is = foldl (.) id (map key is)
path [] = id
path (i:is) = foldl (.) (key i) (map key is)
-- This one doesn't compile
path [] = _Object
path (i:is) = foldl (.) (key i) (map key is)
使用这些定义运行与上面相同的代码块会产生Nothing
,而不是预期的8
。
我几乎可以肯定这是一个类型杂耍的例子,我只是缺少,但我无法弄清楚如何使用一个完整的功能来完成这项工作。预期的行为是path []
为Lens
,它专注于整个json对象。
答案 0 :(得分:2)
对空案例使用_Value
:
> ("null" :: String) ^? _Value
Just Null
> ("null" :: String) ^? (foldl (.) _Value $ map key ["foo", "bar"])
Nothing
> ("{ \"a\": { \"b\": 8} }" :: String) ^? (foldl (.) _Value $ map key ["a", "b"])
Just (Number 8.0)
如您所描述的那样path
不能是Lens
,因为它是部分的(正如您所提到的!),最多只有Traversal
。但是,如果您确定自己在做什么,那么可以使用signular
将Traversal
转换为Lens
。