-- | This module provides a few small functions to make working with -- aeson easier. Hopefully at some point they won't be needed anymore. module Data.Aeson.Utils ( module Data.Aeson , module Data.Aeson.Types -- * Parsing values , decodeV , eitherDecodeV -- * Utilities , fromFloatDigits , (.=?) , parseNumber ) where import Data.Aeson import Data.Aeson.Parser (value) import Data.Aeson.Types import Data.Attoparsec.Lazy (Result (..)) import Data.Scientific import Data.Text (Text) import qualified Data.Attoparsec.Lazy as Atto import qualified Data.ByteString.Lazy as L -- * Parsing values -- | Like 'decodeV', but returns an error message when decoding fails. eitherDecodeV :: FromJSON a => L.ByteString -> Either String a eitherDecodeV v = case Atto.parse value v of Fail _ _ err -> Left err Done _ r -> case fromJSON r of Error e -> Left e Success a -> Right a -- | Deserialize any JSON value. Allows atomic values on the top level decodeV :: FromJSON a => L.ByteString -> Maybe a decodeV = either (const Nothing) Just . eitherDecodeV -- * Utilities -- | Optionally create a Pair. (.=?) :: ToJSON a => Text -> Maybe a -> Maybe Pair k .=? v = fmap (k .=) v {-# INLINE (.=?) #-} -- | Convert a Scientific into an Integer if it doesn't have decimal points, -- otherwise to a Double. parseNumber :: Scientific -> Either Integer Double parseNumber n | e >= 0 = Left $ c * 10 ^ e | otherwise = Right $ realToFrac n where e = base10Exponent n c = coefficient n