{-# LANGUAGE Haskell2010, ScopedTypeVariables, FlexibleInstances, TypeSynonymInstances, OverlappingInstances #-} {-# OPTIONS -Wall -O2 #-} module Text.DeadSimpleJSON.Convert ( Value (..), Convert (..) ) where import Prelude hiding (True, False) import qualified Prelude import Data.Int import Data.Ratio import Text.DeadSimpleJSON.Types import qualified Data.Vector as V -- import qualified Data.Map as M default () class Convert a where convert :: Value -> a convert' :: Value -> Maybe a convert' n@(Number _ _) = return $ convert n convert' _ = fail "" toJSON :: a -> Value toJSON = undefined instance Convert a => Convert (Maybe a) where convert = convert' convert' = maybe Nothing Just . convert' toJSON (Just a) = toJSON a toJSON Nothing = Null instance Convert Value where convert = id convert' = return toJSON = id instance Convert Bool where convert True = Prelude.True convert (String "") = Prelude.False convert (String _) = Prelude.True convert (Number 0 _) = Prelude.False convert (Number _ _) = Prelude.True convert _ = Prelude.False convert' True = return Prelude.True convert' False = return Prelude.False convert' _ = fail "" toJSON (Prelude.True) = True toJSON (Prelude.False) = False instance Convert String where convert (String s) = s convert (Number n e) | e >= 10 = show e | otherwise = show n ++ "e" ++ show e convert (Array arr) = tail $ tail $ V.foldr (\v l -> ", " ++ convert v ++ l) "" arr convert (Object _) = "{object}" convert True = "true" convert False = "false" convert Null = "null" convert' (String s) = return s convert' _ = fail "" toJSON = String instance Convert a => Convert [a] where convert (Array v) = map convert $ V.toList v convert _ = [] convert' arr@(Array _) = return $ convert arr convert' _ = fail "" toJSON = Array . V.fromList . map toJSON instance Convert Double where convert (Number n e) | e >= 0 = fromInteger (n * 10 ^ e) / 1.0 | otherwise = fromInteger n / fromInteger (10 ^ negate e) convert (Object _) = 0/0 convert (Array _) = 0/0 convert Null = 0/0 convert v = def v instance Convert Float where convert (Number n e) | e >= 0 = fromInteger (n * 10 ^ e) / 1.0 | otherwise = fromInteger n / fromInteger (10 ^ negate e) convert (Object _) = 0/0 convert (Array _) = 0/0 convert Null = 0/0 convert v = def v instance forall a. (Read a, Integral a) => Convert (Ratio a) where convert (Number n e) | e >= 0 = n' * 10 ^ e' % 1 | otherwise = n' % 10 ^ negate e' where n' = fromInteger n :: a e' = fromInteger e :: a convert v = def v % 1 instance Convert Integer where convert (Number n e) = int n e convert v = def v toJSON = flip Number 1 instance Convert Int where convert (Number n e) = fromInteger $ int n e convert v = def v toJSON = flip Number 1 . toInteger instance Convert Int8 where convert (Number n e) = fromInteger $ int n e convert v = def v toJSON = flip Number 1 . toInteger instance Convert Int16 where convert (Number n e) = fromInteger $ int n e convert v = def v toJSON = flip Number 1 . toInteger instance Convert Int32 where convert (Number n e) = fromInteger $ int n e convert v = def v toJSON = flip Number 1 . toInteger instance Convert Int64 where convert (Number n e) = fromInteger $ int n e convert v = def v toJSON = flip Number 1 . toInteger int :: Integral a => a -> a -> a int n e | e >= 0 = n * 10 ^ e | otherwise = n `quot` 10 ^ negate e def :: (Read a, Num a) => Value -> a def True = 1 def False = 0 def Null = 0 def (String s) = let v = reads s in case v of ((n, _):_) -> n; _ -> 0 def (Array _) = 0 def (Object _) = 0 def _ = undefined