@@ -59,11 +59,18 @@ module Data.Aeson.Types.FromJSON
5959 -- * Functions
6060 , fromJSON
6161 , ifromJSON
62+ , typeMismatch
63+ , parseField
64+ , parseFieldMaybe
65+ , parseFieldMaybe'
66+ , liftParseField
67+ , liftParseFieldMaybe
68+ , liftParseFieldMaybe'
69+ -- ** Operators
6270 , (.:)
6371 , (.:?)
6472 , (.:!)
6573 , (.!=)
66− , typeMismatch
6774
6875 -- * Internal
6976 , parseOptionalFieldWith
@@ -654,9 +661,7 @@ ifromJSON = iparse parseJSON
654661-- in an object for it to be valid. If the key and value are
655662-- optional, use '.:?' instead.
656663(.:) :: (FromJSON a) => Object -> Text -> Parser a
657−obj .: key = case H.lookup key obj of
658− Nothing -> fail $ "key " ++ show key ++ " not present"
659− Just v -> parseJSON v <?> Key key
664+(.:) = liftParseField parseJSON
660665{-# INLINE (.:) #-}
661666
662667-- | Retrieve the value associated with the given key of an 'Object'. The
@@ -667,9 +672,7 @@ obj .: key = case H.lookup key obj of
667672-- from an object without affecting its validity. If the key and
668673-- value are mandatory, use '.:' instead.
669674(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
670−obj .:? key = case H.lookup key obj of
671− Nothing -> pure Nothing
672− Just v -> parseJSON v <?> Key key
675+(.:?) = liftParseFieldMaybe parseJSON
673676{-# INLINE (.:?) #-}
674677
675678-- | Retrieve the value associated with the given key of an 'Object'.
@@ -679,11 +682,47 @@ obj .:? key = case H.lookup key obj of
679682-- This differs from '.:?' by attempting to parse 'Null' the same as any
680683-- other JSON value, instead of interpreting it as 'Nothing'.
681684(.:!) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
682−obj .:! key = case H.lookup key obj of
683− Nothing -> pure Nothing
684− Just v -> Just <$> parseJSON v <?> Key key
685+(.:!) = liftParseFieldMaybe' parseJSON
685686{-# INLINE (.:!) #-}
686687
688+-- | Function variant of '.:'.
689+parseField :: (FromJSON a) => Object -> Text -> Parser a
690+parseField = (.:)
691+{-# INLINE parseField #-}
692+
693+-- | Function variant of '.:?'.
694+parseFieldMaybe :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
695+parseFieldMaybe = (.:?)
696+{-# INLINE parseFieldMaybe #-}
697+
698+-- | Function variant of '.:!'.
699+parseFieldMaybe' :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
700+parseFieldMaybe' = (.:!)
701+{-# INLINE parseFieldMaybe' #-}
702+
703+-- | Variant of '.:' with explicit parser function.
704+--
705+-- E.g. @'liftParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
706+liftParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
707+liftParseField p obj key = case H.lookup key obj of
708+ Nothing -> fail $ "key " ++ show key ++ " not present"
709+ Just v -> p v <?> Key key
710+{-# INLINE liftParseField #-}
711+
712+-- | Variant of '.:?' with explicit parser function.
713+liftParseFieldMaybe :: (Value -> Parser a) -> Object -> Text -> Parser (Maybe a)
714+liftParseFieldMaybe p obj key = case H.lookup key obj of
715+ Nothing -> pure Nothing
716+ Just v -> liftParseJSON p (listParser p) v <?> Key key -- listParser isn't used by maybe instance.
717+{-# INLINE liftParseFieldMaybe #-}
718+
719+-- | Variant of '.:!' with explicit parser function.
720+liftParseFieldMaybe' :: (Value -> Parser a) -> Object -> Text -> Parser (Maybe a)
721+liftParseFieldMaybe' p obj key = case H.lookup key obj of
722+ Nothing -> pure Nothing
723+ Just v -> Just <$> p v <?> Key key
724+{-# INLINE liftParseFieldMaybe' #-}
725+
687726-- | Helper for use in combination with '.:?' to provide default
688727-- values for optional JSON object fields.
689728--