4

I have an incoming JSON which looks like:

{
  "somekey": [
    { "objectType": "typeA"
    , "key1": "val1"
    , "key2": "val2"
    }
  , { "objectType": "typeB"
    , "key3": "val3"
    , "key4": "val4"
    }
  ]

While parsing, I want to deal with ONLY objects tagged with typeA. I've got the following code to work, but I'm looking at something more idiomatic that will use the power of lenses properly AND will result in a better error message if the parsing fails:

import Control.Lens
import Data.Aeson.Lens (values, key, _String)

instance FromJSON MyType where
  parseJson = Aeson.withObject "Expecting JSON object" $ \o -> do
    allItems <- o .: "someKey"
    let selectedItems :: [Aeson.Value] = filter (\x -> x ^? (key "objectType") . _String == Just "typeA") $ allItems ^.. values 
    someKey <- mapM parseJON selectedItems
    pure MyType{..}
Saurabh Nanda
  • 6,373
  • 5
  • 31
  • 60
  • Could you be clearer? If the code works, what behaviour is it that you don't like, and in what way do you think it needs to be more idiomatic? – Isaac van Bakel Dec 23 '19 at 18:14
  • I asked this 3 months ago, and have forgotten the exact problem I was trying to solve then. Let me take a guess here, now. If the parsing in `mapM parseJSON selectedItems` fails, will the error message be able to identify which element in the array caused the failure? Also, is there a better lens combinator to achieve what the following expression is doing - `filter (\x -> x ^? (key "objectType") . _String == Just "typeA") $ allItems ^.. values` – Saurabh Nanda Dec 29 '19 at 09:44

0 Answers0