干净地访问 lens-aeson 中的嵌套数据

Cleanly accessing nested data in lens-aeson

我有以下代码,但我对它不满意:


import Data.Aeson.Lens
import Data.Aeson.Types
import Data.Text hiding (foldl, map)</p>

<p>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)
</pre>

path 是嵌套 JSON 对象的镜头。例如:

"{ \"a\": { \"b\": 8} }" ^? path ["a", "b"] == Just (Number 8.0)

目前可以用,但有点明显的缺点是功能不全

我尝试了以下定义:

  1. path is = foldl (.) id (map key is)
    
  2. path [] = id
    path (i:is) = foldl (.) (key i) (map key is)
    
  3. -- This one doesn't compile
    path [] = _Object
    path (i:is) = foldl (.) (key i) (map key is)
    

运行 与上述定义相同的代码块产生 Nothing,而不是预期的 8.

我几乎可以肯定这是我所缺少的类型杂耍的情况,但我无法弄清楚如何使它与总功能一起工作。 path [] 的预期行为是一个 Lens,它专注于整个 json 对象。

对空的情况使用_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。然而,如果您真的确定自己在做什么,那么您可以使用 signularTraversal 转换为 Lens