Search code examples
haskellhaskell-lensaeson

Aeson Prisms with "free" references


Just read the brilliant "Lens/Aeson Traversals/Prisms" article and have a real-world application. Given the following anonymized JSON structure, how would I prism out a collection rather than a specific value?

{"Locations" : [ {"id" : "2o8434", "averageReview": ["5", "1"]},{"id" : "2o8435", "averageReview": ["4", "1"]},{"id" : "2o8436", "averageReview": ["3", "1"]},{"id" : "2o8437", "averageReview": ["2", "1"]},{"id" : "2o8438", "averageReview": ["1", "1"]}]}

I have:

λ> locations ^? key "Locations" . nth 0 . key "averageReview" . nth 0
Just (String "5")

What I want:

λ> locations ^? key "Locations" . * . key "averageReview" . nth 0
["5", "4", "3", "2", "1"]

Am I missing the entire point of prisms? Or is this a legitimate use case?

Cheers!


Solution

  • You want to replace nth 0 with values which is a traversal over Aeson arrays.

    Also, since you have a traversal with multiple results and want a list rather than a Maybe, you have to use ^.. instead of ^?.

    *Main> locations ^.. key "Locations" . values . key "averageReview" . nth 0
    [String "5",String "4",String "3",String "2",String "1"]
    

    As Carl helpfully pointed out, you can add a . _String to the end to just get the strings out directly:

    *Main> locations ^.. key "Locations" . values . key "averageReview" . nth 0 . _String
    ["5","4","3","2","1"]