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

    , FlexibleNum (..)

    , resultToEither
    ) 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
[FlexibleNum a] -> ShowS
FlexibleNum a -> String
(Int -> FlexibleNum a -> ShowS)
-> (FlexibleNum a -> String)
-> ([FlexibleNum a] -> ShowS)
-> Show (FlexibleNum a)
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
$cshowsPrec :: forall a. Show a => Int -> FlexibleNum a -> ShowS
showsPrec :: Int -> FlexibleNum a -> ShowS
$cshow :: forall a. Show a => FlexibleNum a -> String
show :: FlexibleNum a -> String
$cshowList :: forall a. Show a => [FlexibleNum a] -> ShowS
showList :: [FlexibleNum a] -> ShowS
Show, [FlexibleNum a] -> Value
[FlexibleNum a] -> Encoding
FlexibleNum a -> Bool
FlexibleNum a -> Value
FlexibleNum a -> Encoding
(FlexibleNum a -> Value)
-> (FlexibleNum a -> Encoding)
-> ([FlexibleNum a] -> Value)
-> ([FlexibleNum a] -> Encoding)
-> (FlexibleNum a -> Bool)
-> ToJSON (FlexibleNum a)
forall a. ToJSON a => [FlexibleNum a] -> Value
forall a. ToJSON a => [FlexibleNum a] -> Encoding
forall a. ToJSON a => FlexibleNum a -> Bool
forall a. ToJSON a => FlexibleNum a -> Value
forall a. ToJSON a => FlexibleNum a -> Encoding
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: forall a. ToJSON a => FlexibleNum a -> Value
toJSON :: FlexibleNum a -> Value
$ctoEncoding :: forall a. ToJSON a => FlexibleNum a -> Encoding
toEncoding :: FlexibleNum a -> Encoding
$ctoJSONList :: forall a. ToJSON a => [FlexibleNum a] -> Value
toJSONList :: [FlexibleNum a] -> Value
$ctoEncodingList :: forall a. ToJSON a => [FlexibleNum a] -> Encoding
toEncodingList :: [FlexibleNum a] -> Encoding
$comitField :: forall a. ToJSON a => FlexibleNum a -> Bool
omitField :: FlexibleNum a -> Bool
ToJSON)

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

resultToEither :: Result a -> Either String a
resultToEither :: forall a. Result a -> Either String a
resultToEither (Success a
x)   = a -> Either String a
forall a b. b -> Either a b
Right a
x
resultToEither (Error   String
err) = String -> Either String a
forall a b. a -> Either a b
Left String
err