aeson-utils-0.2.1.1: src/Data/Aeson/Utils.hs
-- | 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