{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Aeson.Extended
    ( module Data.Aeson

    , FlexibleNum (..)
    ) where

import           Data.Aeson
import qualified Data.Text  as T
import           Prelude
import           Text.Read  (readMaybe)

-- | This can be parsed from a JSON string in addition to a JSON number.
newtype FlexibleNum a = FlexibleNum {forall a. FlexibleNum a -> a
unFlexibleNum :: a}
    deriving (Int -> FlexibleNum a -> ShowS
forall a. Show a => Int -> FlexibleNum a -> ShowS
forall a. Show a => [FlexibleNum a] -> ShowS
forall a. Show a => FlexibleNum a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FlexibleNum a] -> ShowS
$cshowList :: forall a. Show a => [FlexibleNum a] -> ShowS
show :: FlexibleNum a -> String
$cshow :: forall a. Show a => FlexibleNum a -> String
showsPrec :: Int -> FlexibleNum a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> FlexibleNum a -> ShowS
Show, [FlexibleNum a] -> Encoding
[FlexibleNum a] -> Value
FlexibleNum a -> Encoding
FlexibleNum a -> Value
forall a. ToJSON a => [FlexibleNum a] -> Encoding
forall a. ToJSON a => [FlexibleNum a] -> Value
forall a. ToJSON a => FlexibleNum a -> Encoding
forall a. ToJSON a => FlexibleNum a -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [FlexibleNum a] -> Encoding
$ctoEncodingList :: forall a. ToJSON a => [FlexibleNum a] -> Encoding
toJSONList :: [FlexibleNum a] -> Value
$ctoJSONList :: forall a. ToJSON a => [FlexibleNum a] -> Value
toEncoding :: FlexibleNum a -> Encoding
$ctoEncoding :: forall a. ToJSON a => FlexibleNum a -> Encoding
toJSON :: FlexibleNum a -> Value
$ctoJSON :: forall a. ToJSON a => FlexibleNum a -> Value
ToJSON)

instance (FromJSON a, Read a) => FromJSON (FlexibleNum a) where
    parseJSON :: Value -> Parser (FlexibleNum a)
parseJSON (String Text
str) = case forall a. Read a => String -> Maybe a
readMaybe (Text -> String
T.unpack Text
str) of
        Maybe a
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Could not parse " forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
str forall a. [a] -> [a] -> [a]
++ String
" as a number"
        Just a
x  -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> FlexibleNum a
FlexibleNum a
x)
    parseJSON Value
val = forall a. a -> FlexibleNum a
FlexibleNum forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON Value
val