@@ -1,6 +1,12 @@
11{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
22 IncoherentInstances, OverlappingInstances, OverloadedStrings, Rank2Types,
3− ViewPatterns #-}
3+ ViewPatterns, FlexibleContexts, UndecidableInstances,
4+ ScopedTypeVariables, PatternGuards #-}
5+
6+{-# LANGUAGE CPP #-}
7+#ifdef DEFAULT_SIGNATURES
8+{-# LANGUAGE DefaultSignatures #-}
9+#endif
410
511-- |
612-- Module: Data.Aeson.Types
@@ -38,18 +44,24 @@ module Data.Aeson.Types
3844 , (.:)
3945 , (.:?)
4046 , object
47+ -- * Generic toJSON and fromJSON
48+ , genericToJSON
49+ , genericFromJSON
4150 ) where
4251
4352import Control.Applicative
53+import Control.Arrow (first)
54+import Control.Monad.State.Strict
4455import Control.DeepSeq (NFData(..))
45−import Control.Monad (MonadPlus(..), ap)
4656import Data.Aeson.Functions
4757import Data.Attoparsec.Char8 (Number(..))
48−import Data.Data (Data)
58+import Data.Generics
4959import Data.Hashable (Hashable(..))
5060import Data.Int (Int8, Int16, Int32, Int64)
61+import Data.IntSet (IntSet)
5162import Data.List (foldl')
5263import Data.Map (Map)
64+import Data.Maybe (fromJust)
5365import Data.Monoid (Dual(..), First(..), Last(..))
5466import Data.Monoid (Monoid(..))
5567import Data.Ratio (Ratio)
@@ -58,9 +70,9 @@ import Data.Text (Text, pack, unpack)
5870import Data.Text.Encoding (encodeUtf8)
5971import Data.Time.Clock (UTCTime)
6072import Data.Time.Format (FormatTime, formatTime, parseTime)
61−import Data.Typeable (Typeable)
6273import Data.Vector (Vector)
6374import Data.Word (Word, Word8, Word16, Word32, Word64)
75+import Foreign.Storable (Storable)
6476import System.Locale (defaultTimeLocale)
6577import qualified Data.ByteString as B
6678import qualified Data.ByteString.Lazy as LB
@@ -71,7 +83,13 @@ import qualified Data.Map as M
7183import qualified Data.Set as Set
7284import qualified Data.Text as T
7385import qualified Data.Text.Lazy as LT
86+import qualified Data.Traversable as T
7487import qualified Data.Vector as V
88+import qualified Data.Vector.Storable as VS
89+import qualified Data.Vector.Primitive as VP
90+import qualified Data.Vector.Unboxed as VU
91+import qualified Data.Vector.Generic as VG
92+
7593
7694-- | The result of running a 'Parser'.
7795data Result a = Error String
@@ -295,6 +313,11 @@ object = Object . M.fromList
295313class ToJSON a where
296314 toJSON :: a -> Value
297315
316+#ifdef DEFAULT_SIGNATURES
317+ default toJSON :: Data a => a -> Value
318+ toJSON = genericToJSON
319+#endif
320+
298321-- | A type that can be converted from JSON, with the possibility of
299322-- failure.
300323--
@@ -319,6 +342,11 @@ class ToJSON a where
319342class FromJSON a where
320343 parseJSON :: Value -> Parser a
321344
345+#ifdef DEFAULT_SIGNATURES
346+ default parseJSON :: Data a => Value -> Parser a
347+ parseJSON = genericParseJSON
348+#endif
349+
322350instance (ToJSON a) => ToJSON (Maybe a) where
323351 toJSON (Just a) = toJSON a
324352 toJSON Nothing = Null
@@ -574,6 +602,33 @@ instance (FromJSON a) => FromJSON (Vector a) where
574602 parseJSON v = typeMismatch "Vector a" v
575603 {-# INLINE parseJSON #-}
576604
605+vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value
606+vectorToJSON = Array . V.map toJSON . V.convert
607+{-# INLINE vectorToJSON #-}
608+
609+vectorParseJSON :: (FromJSON a, VG.Vector w a) => String -> Value -> Parser (w a)
610+vectorParseJSON _ (Array a) = V.convert <$> V.mapM parseJSON a
611+vectorParseJSON s v = typeMismatch s v
612+{-# INLINE vectorParseJSON #-}
613+
614+instance (Storable a, ToJSON a) => ToJSON (VS.Vector a) where
615+ toJSON = vectorToJSON
616+
617+instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where
618+ parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"
619+
620+instance (VP.Prim a, ToJSON a) => ToJSON (VP.Vector a) where
621+ toJSON = vectorToJSON
622+
623+instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where
624+ parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"
625+
626+instance (VG.Vector VU.Vector a, ToJSON a) => ToJSON (VU.Vector a) where
627+ toJSON = vectorToJSON
628+
629+instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where
630+ parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"
631+
577632instance (ToJSON a) => ToJSON (Set.Set a) where
578633 toJSON = toJSON . Set.toList
579634 {-# INLINE toJSON #-}
@@ -778,3 +833,294 @@ typeMismatch expected actual =
778833 Number _ -> "Number"
779834 Bool _ -> "Boolean"
780835 Null -> "Null"
836+
837+
838+--------------------------------------------------------------------------------
839+-- Generic toJSON and fromJSON
840+
841+type T a = a -> Value
842+
843+genericToJSON :: (Data a) => a -> Value
844+genericToJSON = toJSON_generic
845+ `ext1Q` list
846+ `ext1Q` vector
847+ `ext1Q` set
848+ `ext2Q'` mapAny
849+ `ext2Q'` hashMapAny
850+ -- Use the standard encoding for all base types.
851+ `extQ` (toJSON :: T Integer)
852+ `extQ` (toJSON :: T Int)
853+ `extQ` (toJSON :: T Int8)
854+ `extQ` (toJSON :: T Int16)
855+ `extQ` (toJSON :: T Int32)
856+ `extQ` (toJSON :: T Int64)
857+ `extQ` (toJSON :: T Word)
858+ `extQ` (toJSON :: T Word8)
859+ `extQ` (toJSON :: T Word16)
860+ `extQ` (toJSON :: T Word32)
861+ `extQ` (toJSON :: T Word64)
862+ `extQ` (toJSON :: T Double)
863+ `extQ` (toJSON :: T Number)
864+ `extQ` (toJSON :: T Float)
865+ `extQ` (toJSON :: T Rational)
866+ `extQ` (toJSON :: T Char)
867+ `extQ` (toJSON :: T Text)
868+ `extQ` (toJSON :: T LT.Text)
869+ `extQ` (toJSON :: T String)
870+ `extQ` (toJSON :: T B.ByteString)
871+ `extQ` (toJSON :: T LB.ByteString)
872+ `extQ` (toJSON :: T Value)
873+ `extQ` (toJSON :: T DotNetTime)
874+ `extQ` (toJSON :: T UTCTime)
875+ `extQ` (toJSON :: T IntSet)
876+ `extQ` (toJSON :: T Bool)
877+ `extQ` (toJSON :: T ())
878+ --`extQ` (T.toJSON :: T Ordering)
879+ where
880+ list xs = Array . V.fromList . map genericToJSON $ xs
881+ vector v = Array . V.map genericToJSON $ v
882+ set s = Array . V.fromList . map genericToJSON . Set.toList $ s
883+
884+ mapAny m
885+ | tyrep == typeOf T.empty = remap id
886+ | tyrep == typeOf LT.empty = remap LT.toStrict
887+ | tyrep == typeOf string = remap pack
888+ | tyrep == typeOf B.empty = remap decode
889+ | tyrep == typeOf LB.empty = remap strict
890+ | otherwise = modError "genericToJSON" $
891+ "cannot convert map keyed by type " ++ show tyrep
892+ where tyrep = typeOf . head . M.keys $ m
893+ remap f = Object . transformMap (f . fromJust . cast) genericToJSON $ m
894+
895+ hashMapAny m
896+ | tyrep == typeOf T.empty = remap id
897+ | tyrep == typeOf LT.empty = remap LT.toStrict
898+ | tyrep == typeOf string = remap pack
899+ | tyrep == typeOf B.empty = remap decode
900+ | tyrep == typeOf LB.empty = remap strict
901+ | otherwise = modError "genericToJSON" $
902+ "cannot convert map keyed by type " ++ show tyrep
903+ where tyrep = typeOf . head . H.keys $ m
904+ remap f = Object . hashMap (f . fromJust . cast) genericToJSON $ m
905+
906+
907+toJSON_generic :: (Data a) => a -> Value
908+toJSON_generic = generic
909+ where
910+ -- Generic encoding of an algebraic data type.
911+ generic a =
912+ case dataTypeRep (dataTypeOf a) of
913+ -- No constructor, so it must be an error value. Code
914+ -- it anyway as Null.
915+ AlgRep [] -> Null
916+ -- Elide a single constructor and just code the arguments.
917+ AlgRep [c] -> encodeArgs c (gmapQ genericToJSON a)
918+ -- For multiple constructors, make an object with a
919+ -- field name that is the constructor (except lower
920+ -- case) and the data is the arguments encoded.
921+ AlgRep _ -> encodeConstr (toConstr a) (gmapQ genericToJSON a)
922+ rep -> err (dataTypeOf a) rep
923+ where
924+ err dt r = modError "genericToJSON" $ "not AlgRep " ++
925+ show r ++ "(" ++ show dt ++ ")"
926+ -- Encode nullary constructor as a string.
927+ -- Encode non-nullary constructors as an object with the constructor
928+ -- name as the single field and the arguments as the value.
929+ -- Use an array if the are no field names, but elide singleton arrays,
930+ -- and use an object if there are field names.
931+ encodeConstr c [] = String . constrString $ c
932+ encodeConstr c as = object [(constrString c, encodeArgs c as)]
933+
934+ constrString = pack . showConstr
935+
936+ encodeArgs c = encodeArgs' (constrFields c)
937+ encodeArgs' [] [j] = j
938+ encodeArgs' [] js = Array . V.fromList $ js
939+ encodeArgs' ns js = object $ zip (map mungeField ns) js
940+
941+ -- Skip leading '_' in field name so we can use keywords
942+ -- etc. as field names.
943+ mungeField ('_':cs) = pack cs
944+ mungeField cs = pack cs
945+
946+genericFromJSON :: (Data a) => Value -> Result a
947+genericFromJSON = parse genericParseJSON
948+
949+type F a = Parser a
950+
951+genericParseJSON :: (Data a) => Value -> Parser a
952+genericParseJSON j = parseJSON_generic j
953+ `ext1R` list
954+ `ext1R` vector
955+ `ext2R'` mapAny
956+ `ext2R'` hashMapAny
957+ -- Use the standard encoding for all base types.
958+ `extR` (value :: F Integer)
959+ `extR` (value :: F Int)
960+ `extR` (value :: F Int8)
961+ `extR` (value :: F Int16)
962+ `extR` (value :: F Int32)
963+ `extR` (value :: F Int64)
964+ `extR` (value :: F Word)
965+ `extR` (value :: F Word8)
966+ `extR` (value :: F Word16)
967+ `extR` (value :: F Word32)
968+ `extR` (value :: F Word64)
969+ `extR` (value :: F Double)
970+ `extR` (value :: F Number)
971+ `extR` (value :: F Float)
972+ `extR` (value :: F Rational)
973+ `extR` (value :: F Char)
974+ `extR` (value :: F Text)
975+ `extR` (value :: F LT.Text)
976+ `extR` (value :: F String)
977+ `extR` (value :: F B.ByteString)
978+ `extR` (value :: F LB.ByteString)
979+ `extR` (value :: F Value)
980+ `extR` (value :: F DotNetTime)
981+ `extR` (value :: F UTCTime)
982+ `extR` (value :: F IntSet)
983+ `extR` (value :: F Bool)
984+ `extR` (value :: F ())
985+ where
986+ value :: (FromJSON a) => Parser a
987+ value = parseJSON j
988+ list :: (Data a) => Parser [a]
989+ list = V.toList <$> genericParseJSON j
990+ vector :: (Data a) => Parser (V.Vector a)
991+ vector = case j of
992+ Array js -> V.mapM genericParseJSON js
993+ _ -> myFail
994+ mapAny :: forall e f. (Data e, Data f) => Parser (Map f e)
995+ mapAny
996+ | tyrep `elem` stringyTypes = res
997+ | otherwise = myFail
998+ where res = case j of
999+ Object js -> M.mapKeysMonotonic trans <$> T.mapM genericParseJSON js
1000+ _ -> myFail
1001+ trans
1002+ | tyrep == typeOf T.empty = remap id
1003+ | tyrep == typeOf LT.empty = remap LT.fromStrict
1004+ | tyrep == typeOf string = remap T.unpack
1005+ | tyrep == typeOf B.empty = remap encodeUtf8
1006+ | tyrep == typeOf LB.empty = remap lazy
1007+ | otherwise = modError "genericParseJSON"
1008+ "mapAny -- should never happen"
1009+ tyrep = typeOf (undefined :: f)
1010+ remap f = fromJust . cast . f
1011+ hashMapAny :: forall e f. (Data e, Data f) => Parser (H.HashMap f e)
1012+ hashMapAny
1013+ | tyrep == typeOf string = process T.unpack
1014+ | tyrep == typeOf LT.empty = process LT.fromStrict
1015+ | tyrep == typeOf T.empty = process id
1016+ | otherwise = myFail
1017+ where
1018+ process f = maybe myFail return . cast =<< parseWith f
1019+ parseWith :: (Eq c, Hashable c) => (Text -> c) -> Parser (H.HashMap c e)
1020+ parseWith f = case j of
1021+ Object js -> H.fromList . map (first f) . M.toList <$>
1022+ T.mapM genericParseJSON js
1023+ _ -> myFail
1024+ tyrep = typeOf (undefined :: f)
1025+ myFail = modFail "genericParseJSON" $ "bad data: " ++ show j
1026+ stringyTypes = [typeOf LT.empty, typeOf T.empty, typeOf B.empty,
1027+ typeOf LB.empty, typeOf string]
1028+
1029+parseJSON_generic :: (Data a) => Value -> Parser a
1030+parseJSON_generic j = generic
1031+ where
1032+ typ = dataTypeOf $ resType generic
1033+ generic = case dataTypeRep typ of
1034+ AlgRep [] -> case j of
1035+ Null -> return (modError "genericParseJSON" "empty type")
1036+ _ -> modFail "genericParseJSON" "no-constr bad data"
1037+ AlgRep [_] -> decodeArgs (indexConstr typ 1) j
1038+ AlgRep _ -> do (c, j') <- getConstr typ j; decodeArgs c j'
1039+ rep -> modFail "genericParseJSON" $
1040+ show rep ++ "(" ++ show typ ++ ")"
1041+ getConstr t (Object o) | [(s, j')] <- fromJSObject o = do
1042+ c <- readConstr' t s
1043+ return (c, j')
1044+ getConstr t (String js) = do c <- readConstr' t (unpack js)
1045+ return (c, Null) -- handle nullary ctor
1046+ getConstr _ _ = modFail "genericParseJSON" "bad constructor encoding"
1047+ readConstr' t s =
1048+ maybe (modFail "genericParseJSON" $ "unknown constructor: " ++ s ++ " " ++
1049+ show t)
1050+ return $ readConstr t s
1051+
1052+ decodeArgs c0 = go (numConstrArgs (resType generic) c0) c0
1053+ (constrFields c0)
1054+ where
1055+ go 0 c _ Null = construct c [] -- nullary constructor
1056+ go 1 c [] jd = construct c [jd] -- unary constructor
1057+ go n c [] (Array js)
1058+ | n > 1 = construct c (V.toList js) -- no field names
1059+ -- FIXME? We could allow reading an array into a constructor
1060+ -- with field names.
1061+ go _ c fs@(_:_) (Object o) = selectFields o fs >>=
1062+ construct c -- field names
1063+ go _ c _ jd = modFail "genericParseJSON" $
1064+ "bad decodeArgs data " ++ show (c, jd)
1065+
1066+ fromJSObject = map (first unpack) . M.toList
1067+
1068+ -- Build the value by stepping through the list of subparts.
1069+ construct c = evalStateT $ fromConstrM f c
1070+ where f :: (Data a) => StateT [Value] Parser a
1071+ f = do js <- get
1072+ case js of
1073+ [] -> lift $ modFail "construct" "empty list"
1074+ (j':js') -> do put js'; lift $ genericParseJSON j'
1075+
1076+ -- Select the named fields from a JSON object.
1077+ selectFields fjs = mapM sel
1078+ where sel f = maybe (modFail "genericParseJSON" $ "field does not exist " ++
1079+ f) return $ M.lookup (pack f) fjs
1080+
1081+ -- Count how many arguments a constructor has. The value x is
1082+ -- used to determine what type the constructor returns.
1083+ numConstrArgs :: (Data a) => a -> Constr -> Int
1084+ numConstrArgs x c = execState (fromConstrM f c `asTypeOf` return x) 0
1085+ where f = do modify (+1); return undefined
1086+
1087+ resType :: MonadPlus m => m a -> a
1088+ resType _ = modError "genericParseJSON" "resType"
1089+
1090+modFail :: (Monad m) => String -> String -> m a
1091+modFail func err = fail $ "Data.Aeson.Types." ++ func ++ ": " ++ err
1092+
1093+modError :: String -> String -> a
1094+modError func err = error $ "Data.Aeson.Types." ++ func ++ ": " ++ err
1095+
1096+string :: String
1097+string = ""
1098+
1099+-- Type extension for binary type constructors.
1100+
1101+-- | Flexible type extension
1102+ext2' :: (Data a, Typeable2 t)
1103+ => c a
1104+ -> (forall d1 d2. (Data d1, Data d2) => c (t d1 d2))
1105+ -> c a
1106+ext2' def ext = maybe def id (dataCast2 ext)
1107+
1108+-- | Type extension of queries for type constructors
1109+ext2Q' :: (Data d, Typeable2 t)
1110+ => (d -> q)
1111+ -> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q)
1112+ -> d -> q
1113+ext2Q' def ext = unQ ((Q def) `ext2'` (Q ext))
1114+
1115+-- | Type extension of readers for type constructors
1116+ext2R' :: (Monad m, Data d, Typeable2 t)
1117+ => m d
1118+ -> (forall d1 d2. (Data d1, Data d2) => m (t d1 d2))
1119+ -> m d
1120+ext2R' def ext = unR ((R def) `ext2'` (R ext))
1121+
1122+-- | The type constructor for queries
1123+newtype Q q x = Q { unQ :: x -> q }
1124+
1125+-- | The type constructor for readers
1126+newtype R m x = R { unR :: m x }