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

时间:2017-06-22 14:09:31

标签: json haskell lens aeson

我想做以下测试通过:

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之类的东西或transform,但是我无法使其成功,可能是由于缺乏对镜头的深刻理解。

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

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

1 个答案:

答案 0 :(得分:2)

一种方法是使用transformOndeep来精确控制转换的应用位置。

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*系列函数以递归方式应用其修改,这对于您想要进行的修改来说是过度的。