@@ -55,6 +55,7 @@ module Data.Aeson.Types.FromJSON
55 , withNumber
55 , withNumber
56 , withScientific
56 , withScientific
57 , withBool
57 , withBool
59 -- * Functions
60 -- * Functions
60 , fromJSON
61 , fromJSON
@@ -82,6 +83,7 @@ import Prelude.Compat
82import Control.Applicative ((<|>), Const(..))
83import Control.Applicative ((<|>), Const(..))
83import Control.Monad ((<=<), zipWithM)
84import Control.Monad ((<=<), zipWithM)
84import Data.Aeson.Internal.Functions (mapKey)
85import Data.Aeson.Internal.Functions (mapKey)
86+import Data.Aeson.Parser.Internal (eitherDecodeWith, jsonEOF)
85import Data.Aeson.Types.Generic
87import Data.Aeson.Types.Generic
86import Data.Aeson.Types.Internal
88import Data.Aeson.Types.Internal
87import Data.Attoparsec.Number (Number(..))
89import Data.Attoparsec.Number (Number(..))
@@ -114,6 +116,7 @@ import GHC.Generics
114import Numeric.Natural (Natural)
116import Numeric.Natural (Natural)
115import Text.ParserCombinators.ReadP (readP_to_S)
117import Text.ParserCombinators.ReadP (readP_to_S)
116import Unsafe.Coerce (unsafeCoerce)
118import Unsafe.Coerce (unsafeCoerce)
119+import qualified Data.Aeson.Compat as Compat
117import qualified Data.Aeson.Parser.Time as Time
120import qualified Data.Aeson.Parser.Time as Time
118import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
121import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
119import qualified Data.DList as DList
122import qualified Data.DList as DList
@@ -665,6 +668,16 @@ withBool _ f (Bool arr) = f arr
665withBool expected _ v = typeMismatch expected v
668withBool expected _ v = typeMismatch expected v
666{-# INLINE withBool #-}
669{-# INLINE withBool #-}
671+-- | Decode a nested JSON-encoded string.
672+withEmbeddedJSON :: (FromJSON a) => String -> (Value -> Parser a) -> Value -> Parser a
673+withEmbeddedJSON _ innerParser (String txt) =
674+ either fail innerParser $ eitherDecode (Compat.fromStrict $ T.encodeUtf8 txt)
676+ eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
677+ eitherFormatError = either (Left . uncurry formatError) Right
678+withEmbeddedJSON name _ v = typeMismatch name v
679+{-# INLINE withEmbeddedJSON #-}
668-- | Convert a value from JSON, failing if the types do not match.
681-- | Convert a value from JSON, failing if the types do not match.
669fromJSON :: (FromJSON a) => Value -> Result a
682fromJSON :: (FromJSON a) => Value -> Result a
670fromJSON = parse parseJSON
683fromJSON = parse parseJSON