如何使用 haskell 镜头重写 JSON 结构中的任意嵌套字段?

How can I rewrite an arbitrarily nested field in a JSON structure using haskell lenses?

我想通过以下测试:

it "can rewrite a field from an object" $ do
  let _42 = 42 :: Int
      nested =  object [ "foo" .= _42, "baz" .= object [ "bar" .= _42 ] ]
                                           ]
  rewrite "bar" nested  `shouldBe` object [ "foo" .= _42
                                          , "baz" .= object [ "bar" .= ("XXXXXXXX" :: Text) ]
                                          ]

好像我想要的是Control.Lens.Plated的东西,比如rewrite like or transform,但我做不到,可能是对镜头的理解不够深入。

我设法使用以下代码更改了一个图层,但想将其用于嵌套字段。

 rewrite' field value = value & key field %~ const "XXXXXXXX"

一种方法是使用 transformOn along with deep 来精确控制应用转换的位置。

ghci> let nested = object [ "foo" .= 42, "baz" .= object [ "bar" .= 42 ] ]
ghci> transformOn (deep $ key "bar") (const "XXXXXXXX") nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

deepPlated 结构中搜索所提供的 Traversal 匹配的位置,并且 transformOn 将更改应用于其每个目标。

编辑:

我刚刚意识到 transformOn 太过分了。您可以只使用 deep 和更简单的镜头组合器:

ghci> deep (key "bar") %~ const "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

甚至

ghci> deep (key "bar") .~ "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

transform* 函数族以递归方式应用其修改,这对于您要进行的修改来说太过分了。