2017-06-22 5 views
2

Je voudrais faire passer le test suivant:Comment puis-je réécrire un champ arbitrairement imbriqué dans une structure JSON en utilisant des lentilles Haskell?

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) ] 
              ] 

Il semble que ce que je veux quelque chose de Control.Lens.Plated comme rewrite comme ou transform, mais je ne peux pas réussir à le faire fonctionner, probablement en raison du manque une compréhension profonde de lentilles.

J'ai réussi à modifier une couche unique en utilisant le code suivant, mais je voudrais tirer parti de cela pour les champs imbriqués.

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

Est-ce que '\ field -> transformer (réécrire le champ)' fait ce que vous voulez? (Juste une supposition - je ne suis pas un expert de la lentille non plus) – user2407038

Répondre

2

Une approche consiste à utiliser transformOn avec deep pour obtenir un contrôle précis sur l'où la transformation est appliquée.

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")]))]) 

deep recherche une structure de Plated pour les endroits où la condition Traversal matches, et transformOn applique un changement à chacun de ses objectifs.

EDIT:

Je viens de réaliser transformOn est surpuissant massif pour cela. Vous pouvez vous en sortir avec juste deep et plus simples lentilles combinators:

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

ou même

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

La famille transform* des fonctions applique ses modifications récursive, ce qui est trop pour la modification que vous voulez faire.