@@ -5,16 +5,20 @@
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GADTs #-}
6{-# LANGUAGE GADTs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE NamedFieldPuns #-}
8{-# LANGUAGE NoImplicitPrelude #-}
9{-# LANGUAGE NoImplicitPrelude #-}
9{-# LANGUAGE OverloadedStrings #-}
10{-# LANGUAGE OverloadedStrings #-}
10−{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE RecordWildCards #-}
11{-# LANGUAGE RecordWildCards #-}
12{-# LANGUAGE ScopedTypeVariables #-}
12{-# LANGUAGE ScopedTypeVariables #-}
13{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE TypeOperators #-}
14−{-# LANGUAGE TupleSections #-}
14+{-# LANGUAGE TypeSynonymInstances #-}
15{-# LANGUAGE UndecidableInstances #-}
15{-# LANGUAGE UndecidableInstances #-}
16{-# LANGUAGE ViewPatterns #-}
16{-# LANGUAGE ViewPatterns #-}
18+#if __GLASGOW_HASKELL__ >= 706
19+{-# LANGUAGE PolyKinds #-}
18#include "incoherent-compat.h"
22#include "incoherent-compat.h"
19#include "overlapping-compat.h"
23#include "overlapping-compat.h"
@@ -42,9 +46,6 @@ module Data.Aeson.Types.FromJSON
42 , coerceFromJSONKeyFunction
46 , coerceFromJSONKeyFunction
43 , mapFromJSONKeyFunction
47 , mapFromJSONKeyFunction
48 -- * List functions
49 -- * List functions
49 , listParser
50 , listParser
@@ -87,7 +88,7 @@ import Data.Aeson.Parser.Internal (eitherDecodeWith, jsonEOF)
87import Data.Aeson.Types.Generic
88import Data.Aeson.Types.Generic
88import Data.Aeson.Types.Internal
89import Data.Aeson.Types.Internal
89import Data.Bits (unsafeShiftR)
90import Data.Bits (unsafeShiftR)
90−import Data.Fixed (Fixed, HasResolution (resolution), Nano)
91+import Data.Fixed (Fixed, HasResolution)
91import Data.Functor.Compose (Compose(..))
92import Data.Functor.Compose (Compose(..))
92import Data.Functor.Identity (Identity(..))
93import Data.Functor.Identity (Identity(..))
93import Data.Functor.Product (Product(..))
94import Data.Functor.Product (Product(..))
@@ -103,10 +104,8 @@ import Data.Scientific (Scientific, base10Exponent)
103import Data.Tagged (Tagged(..))
104import Data.Tagged (Tagged(..))
104import Data.Text (Text, pack, unpack)
105import Data.Text (Text, pack, unpack)
105import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
106import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
106−import Data.Time.Calendar.Compat (CalendarDiffDays (..), DayOfWeek (..))
107+import Data.Time.Format (parseTime)
107−import Data.Time.LocalTime.Compat (CalendarDiffTime (..))
108−import Data.Time.Clock.System.Compat (SystemTime (..))
109−import Data.Time.Format.Compat (parseTimeM, defaultTimeLocale)
108+import Data.Time.Locale.Compat (defaultTimeLocale)
110import Data.Traversable as Tr (sequence)
109import Data.Traversable as Tr (sequence)
111import Data.Vector (Vector)
110import Data.Vector (Vector)
112import Data.Version (Version, parseVersion)
111import Data.Version (Version, parseVersion)
@@ -118,9 +117,9 @@ import GHC.Generics
118import Numeric.Natural (Natural)
117import Numeric.Natural (Natural)
119import Text.ParserCombinators.ReadP (readP_to_S)
118import Text.ParserCombinators.ReadP (readP_to_S)
120import Unsafe.Coerce (unsafeCoerce)
119import Unsafe.Coerce (unsafeCoerce)
120+import qualified Data.Aeson.Compat as Compat
121import qualified Data.Aeson.Parser.Time as Time
121import qualified Data.Aeson.Parser.Time as Time
122import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
122import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
123−import qualified Data.ByteString.Lazy as L
124import qualified Data.DList as DList
123import qualified Data.DList as DList
125import qualified Data.HashMap.Strict as H
124import qualified Data.HashMap.Strict as H
126import qualified Data.HashSet as HashSet
125import qualified Data.HashSet as HashSet
@@ -149,14 +148,22 @@ import qualified Data.Primitive.SmallArray as PM
149import qualified Data.Primitive.Types as PM
148import qualified Data.Primitive.Types as PM
151#if MIN_VERSION_primitive(0,6,4)
150#if MIN_VERSION_primitive(0,6,4)
152−#if !MIN_VERSION_primitive(0,7,0)
153import qualified Data.Primitive.UnliftedArray as PM
151import qualified Data.Primitive.UnliftedArray as PM
155import qualified Data.Primitive.PrimArray as PM
152import qualified Data.Primitive.PrimArray as PM
155+#ifndef HAS_COERCIBLE
156+#define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 707)
159import Data.Coerce (Coercible, coerce)
160import Data.Coerce (Coercible, coerce)
161+coerce' :: Coercible a b => a -> b
165+coerce' = unsafeCoerce
161parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
168parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
162parseIndexedJSON p idx value = p value <?> Index idx
169parseIndexedJSON p idx value = p value <?> Index idx
@@ -396,16 +403,6 @@ class FromJSON a where
396-- > newtype SomeId = SomeId { getSomeId :: Text }
403-- > newtype SomeId = SomeId { getSomeId :: Text }
397-- > deriving (Eq,Ord,Hashable,FromJSONKey)
404-- > deriving (Eq,Ord,Hashable,FromJSONKey)
399−-- If you have a sum of nullary constructors, you may use the generic
403−-- data Color = Red | Green | Blue
406−-- instance 'FromJSONKey' Color where
407−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
409class FromJSONKey a where
406class FromJSONKey a where
410 -- | Strategy for parsing the key of a map-like container.
407 -- | Strategy for parsing the key of a map-like container.
411 fromJSONKey :: FromJSONKeyFunction a
408 fromJSONKey :: FromJSONKeyFunction a
@@ -428,7 +425,11 @@ class FromJSONKey a where
428-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
425-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
429-- can be inspected, but cannot be constructed.
426-- can be inspected, but cannot be constructed.
430data CoerceText a where
427data CoerceText a where
431 CoerceText :: Coercible Text a => CoerceText a
429 CoerceText :: Coercible Text a => CoerceText a
431+ CoerceText :: CoerceText a
433-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
434-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
434-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
435-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
@@ -448,7 +449,7 @@ data FromJSONKeyFunction a
449-- | Only law abiding up to interpretation
450-- | Only law abiding up to interpretation
450instance Functor FromJSONKeyFunction where
451instance Functor FromJSONKeyFunction where
451− fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce)
452+ fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
452 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
453 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
453 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
454 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
454 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
455 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
@@ -462,7 +463,9 @@ instance Functor FromJSONKeyFunction where
463-- On pre GHC 7.8 this is unconstrainted function.
464-- On pre GHC 7.8 this is unconstrainted function.
464fromJSONKeyCoerce ::
465fromJSONKeyCoerce ::
465 Coercible Text a =>
467 Coercible Text a =>
466 FromJSONKeyFunction a
469 FromJSONKeyFunction a
467fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
470fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
@@ -470,52 +473,34 @@ fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
471-- See note on 'fromJSONKeyCoerce'.
474-- See note on 'fromJSONKeyCoerce'.
472coerceFromJSONKeyFunction ::
475coerceFromJSONKeyFunction ::
473 Coercible a b =>
477 Coercible a b =>
474 FromJSONKeyFunction a -> FromJSONKeyFunction b
479 FromJSONKeyFunction a -> FromJSONKeyFunction b
475coerceFromJSONKeyFunction = coerce
481coerceFromJSONKeyFunction = coerce
483+coerceFromJSONKeyFunction (FromJSONKeyCoerce CoerceText) = FromJSONKeyCoerce CoerceText
484+coerceFromJSONKeyFunction (FromJSONKeyText f) = FromJSONKeyText (coerce' . f)
485+coerceFromJSONKeyFunction (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap coerce' . f)
486+coerceFromJSONKeyFunction (FromJSONKeyValue f) = FromJSONKeyValue (fmap coerce' . f)
478 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
490 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
479 fmap id x = x
491 fmap id x = x
482 "FromJSONKeyCoerce: fmap coerce" forall x .
495 "FromJSONKeyCoerce: fmap coerce" forall x .
483 fmap coerce x = coerceFromJSONKeyFunction x
496 fmap coerce x = coerceFromJSONKeyFunction x
486-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
500-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
487mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
501mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
488mapFromJSONKeyFunction = fmap
502mapFromJSONKeyFunction = fmap
490−-- | 'fromJSONKey' for 'Generic' types.
491−-- These types must be sums of nullary constructors, whose names will be used
492−-- as keys for JSON objects.
494−-- See also 'genericToJSONKey'.
499−-- data Color = Red | Green | Blue
500−-- deriving 'Generic'
502−-- instance 'FromJSONKey' Color where
503−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
505−genericFromJSONKey :: forall a. (Generic a, GFromJSONKey (Rep a))
507− -> FromJSONKeyFunction a
508−genericFromJSONKey opts = FromJSONKeyTextParser $ \t ->
509− case parseSumFromString (keyModifier opts) t of
511− "invalid key " ++ show t ++ ", expected one of " ++ show cnames
512− Just k -> pure (to k)
514− cnames = unTagged2 (constructorTags (keyModifier opts) :: Tagged2 (Rep a) [String])
516−class (ConstructorNames f, SumFromString f) => GFromJSONKey f where
517−instance (ConstructorNames f, SumFromString f) => GFromJSONKey f where
519-------------------------------------------------------------------------------
504-------------------------------------------------------------------------------
520-- Functions needed for documentation
505-- Functions needed for documentation
521-------------------------------------------------------------------------------
506-------------------------------------------------------------------------------
@@ -768,13 +753,13 @@ withBoundedScientific' f v = withBoundedScientific_ id f v
768-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
753-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
769-- to the 'Parser' in case of failure.
754-- to the 'Parser' in case of failure.
770withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
755withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
771−withBoundedScientific_ whenFail f (Number scientific) =
756+withBoundedScientific_ whenFail f v@(Number scientific) =
772− if exp10 > 1024
757+ if exponent > 1024
773 then whenFail (fail msg)
758 then whenFail (fail msg)
774 else f scientific
759 else f scientific
776− exp10 = base10Exponent scientific
761+ exponent = base10Exponent scientific
777− msg = "found a number with exponent " ++ show exp10 ++ ", but it must not be greater than 1024"
762+ msg = "found a number with exponent " ++ show exponent ++ ", but it must not be greater than 1024"
778withBoundedScientific_ whenFail _ v =
763withBoundedScientific_ whenFail _ v =
779 whenFail (typeMismatch "Number" v)
764 whenFail (typeMismatch "Number" v)
780{-# INLINE withBoundedScientific_ #-}
765{-# INLINE withBoundedScientific_ #-}
@@ -794,7 +779,7 @@ withBool name _ v = prependContext name (typeMismatch "Boolean" v)
794-- | Decode a nested JSON-encoded string.
779-- | Decode a nested JSON-encoded string.
795withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
780withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
796withEmbeddedJSON _ innerParser (String txt) =
781withEmbeddedJSON _ innerParser (String txt) =
797− either fail innerParser $ eitherDecode (L.fromStrict $ T.encodeUtf8 txt)
782+ either fail innerParser $ eitherDecode (Compat.fromStrict $ T.encodeUtf8 txt)
799 eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
784 eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
800 eitherFormatError = either (Left . uncurry formatError) Right
785 eitherFormatError = either (Left . uncurry formatError) Right
@@ -863,7 +848,7 @@ parseFieldMaybe' = (.:!)
863-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
848-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
864explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
849explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
865explicitParseField p obj key = case H.lookup key obj of
850explicitParseField p obj key = case H.lookup key obj of
866− Nothing -> fail $ "key " ++ show key ++ " not found"
851+ Nothing -> fail $ "key " ++ show key ++ " not present"
867 Just v -> p v <?> Key key
852 Just v -> p v <?> Key key
868{-# INLINE explicitParseField #-}
853{-# INLINE explicitParseField #-}
@@ -922,16 +907,6 @@ type ConName = String
922contextType :: TypeName -> Parser a -> Parser a
907contextType :: TypeName -> Parser a -> Parser a
923contextType = prependContext
908contextType = prependContext
925−-- | Add the tagKey that will be looked up while building an ADT
926−-- | Produce the error equivalent to
927−-- | Left "Error in $: parsing T failed, expected an object with keys "tag" and
928−-- | "contents", where "tag" i-- |s associated to one of ["Foo", "Bar"],
929−-- | The parser returned error was: could not find key "tag"
930−contextTag :: Text -> [String] -> Parser a -> Parser a
931−contextTag tagKey cnames = prependFailure
932− ("expected Object with key \"" ++ unpack tagKey ++ "\"" ++
933− " containing one of " ++ show cnames ++ ", ")
935-- | Add the name of the constructor being parsed to a parser's error messages.
910-- | Add the name of the constructor being parsed to a parser's error messages.
936contextCons :: ConName -> TypeName -> Parser a -> Parser a
911contextCons :: ConName -> TypeName -> Parser a -> Parser a
937contextCons cname tname = prependContext (showCons cname tname)
912contextCons cname tname = prependContext (showCons cname tname)
@@ -1042,46 +1017,41 @@ parseAllNullarySum :: (SumFromString f, ConstructorNames f)
1042parseAllNullarySum tname opts =
1017parseAllNullarySum tname opts =
1043 withText tname $ \tag ->
1018 withText tname $ \tag ->
1044 maybe (badTag tag) return $
1019 maybe (badTag tag) return $
1045− parseSumFromString modifier tag
1020+ parseSumFromString opts tag
1047− badTag tag = failWithCTags tname modifier $ \cnames ->
1022+ badTag tag = failWithCTags tname opts $ \cnames ->
1048 "expected one of the tags " ++ show cnames ++
1023 "expected one of the tags " ++ show cnames ++
1049 ", but found tag " ++ show tag
1024 ", but found tag " ++ show tag
1050− modifier = constructorTagModifier opts
1052-- | Fail with an informative error message about a mismatched tag.
1026-- | Fail with an informative error message about a mismatched tag.
1053-- The error message is parameterized by the list of expected tags,
1027-- The error message is parameterized by the list of expected tags,
1054-- to be inferred from the result type of the parser.
1028-- to be inferred from the result type of the parser.
1055failWithCTags
1029failWithCTags
1056− :: forall f a t. ConstructorNames f
1030+ :: forall f a. ConstructorNames f
1057− => TypeName -> (String -> t) -> ([t] -> String) -> Parser (f a)
1031+ => TypeName -> Options -> ([String] -> String) -> Parser (f a)
1058−failWithCTags tname modifier f =
1032+failWithCTags tname opts f =
1059 contextType tname . fail $ f cnames
1033 contextType tname . fail $ f cnames
1061− cnames = unTagged2 (constructorTags modifier :: Tagged2 f [t])
1035+ cnames = unTagged2 (constructorTags opts :: Tagged2 f [String])
1063class SumFromString f where
1037class SumFromString f where
1064− parseSumFromString :: (String -> String) -> Text -> Maybe (f a)
1038+ parseSumFromString :: Options -> Text -> Maybe (f a)
1066instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
1040instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
1067 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
1041 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
1068 (R1 <$> parseSumFromString opts key)
1042 (R1 <$> parseSumFromString opts key)
1070instance (Constructor c) => SumFromString (C1 c U1) where
1044instance (Constructor c) => SumFromString (C1 c U1) where
1071− parseSumFromString modifier key
1045+ parseSumFromString opts key | key == name = Just $ M1 U1
1072− | key == name = Just $ M1 U1
1073− | otherwise = Nothing
1046+ | otherwise = Nothing
1048+ name = pack $ constructorTagModifier opts $
1075− name = pack $ modifier $ conName (undefined :: M1 _i c _f _p)
1049+ conName (undefined :: M1 _i c _f _p)
1077−-- For genericFromJSONKey
1078−instance SumFromString a => SumFromString (D1 d a) where
1079− parseSumFromString modifier key = M1 <$> parseSumFromString modifier key
1081-- | List of all constructor tags.
1051-- | List of all constructor tags.
1082−constructorTags :: ConstructorNames a => (String -> t) -> Tagged2 a [t]
1052+constructorTags :: ConstructorNames a => Options -> Tagged2 a [String]
1083−constructorTags modifier =
1053+constructorTags opts =
1084− fmap DList.toList (constructorNames' modifier)
1054+ fmap DList.toList (constructorNames' (constructorTagModifier opts))
1086-- | List of all constructor names of an ADT, after a given conversion
1056-- | List of all constructor names of an ADT, after a given conversion
1087-- function. (Better inlining.)
1057-- function. (Better inlining.)
@@ -1102,16 +1072,9 @@ instance Constructor c => ConstructorNames (C1 c a) where
1103 cname = conName (undefined :: M1 _i c _f _p)
1073 cname = conName (undefined :: M1 _i c _f _p)
1105−-- For genericFromJSONKey
1106−instance ConstructorNames a => ConstructorNames (D1 d a) where
1107− constructorNames' = retag . constructorNames'
1109− retag :: Tagged2 a u -> Tagged2 (D1 d a) u
1110− retag (Tagged2 x) = Tagged2 x
1112--------------------------------------------------------------------------------
1075--------------------------------------------------------------------------------
1113−parseNonAllNullarySum :: forall f c arity.
1077+parseNonAllNullarySum :: ( FromPair arity f
1115 , FromTaggedObject arity f
1078 , FromTaggedObject arity f
1116 , FromUntaggedValue arity f
1079 , FromUntaggedValue arity f
1117 , ConstructorNames f
1080 , ConstructorNames f
@@ -1121,7 +1084,7 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1121 case sumEncoding opts of
1084 case sumEncoding opts of
1122 TaggedObject{..} ->
1085 TaggedObject{..} ->
1123 withObject tname $ \obj -> do
1086 withObject tname $ \obj -> do
1124− tag <- contextType tname . contextTag tagKey cnames_ $ obj .: tagKey
1087+ tag <- contextType tname $ obj .: tagKey
1125 fromMaybe (badTag tag <?> Key tagKey) $
1088 fromMaybe (badTag tag <?> Key tagKey) $
1126 parseFromTaggedObject (tag :* contentsFieldName :* p) obj
1089 parseFromTaggedObject (tag :* contentsFieldName :* p) obj
@@ -1129,7 +1092,6 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1129 badTag tag = failWith_ $ \cnames ->
1092 badTag tag = failWith_ $ \cnames ->
1130 "expected tag field to be one of " ++ show cnames ++
1093 "expected tag field to be one of " ++ show cnames ++
1131 ", but found tag " ++ show tag
1094 ", but found tag " ++ show tag
1132− cnames_ = unTagged2 (constructorTags (constructorTagModifier opts) :: Tagged2 f [String])
1134 ObjectWithSingleField ->
1096 ObjectWithSingleField ->
1135 withObject tname $ \obj -> case H.toList obj of
1097 withObject tname $ \obj -> case H.toList obj of
@@ -1161,7 +1123,7 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1162 UntaggedValue -> parseUntaggedValue p
1124 UntaggedValue -> parseUntaggedValue p
1164− failWith_ = failWithCTags tname (constructorTagModifier opts)
1126+ failWith_ = failWithCTags tname opts
1166--------------------------------------------------------------------------------
1128--------------------------------------------------------------------------------
@@ -1201,9 +1163,9 @@ class FromTaggedObject' arity f isRecord where
1201 :: String :* ConName :* TypeName :* Options :* FromArgs arity a
1163 :: String :* ConName :* TypeName :* Options :* FromArgs arity a
1202 -> Object -> Tagged isRecord (Parser (f a))
1164 -> Object -> Tagged isRecord (Parser (f a))
1204−instance (RecordFromJSON arity f, FieldNames f) => FromTaggedObject' arity f True where
1166+instance (RecordFromJSON arity f) => FromTaggedObject' arity f True where
1205 -- Records are unpacked in the tagged object
1167 -- Records are unpacked in the tagged object
1206− parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON (True :* p)
1168+ parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON p
1208instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
1170instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
1209 -- Nonnullary nonrecords are encoded in the contents field
1171 -- Nonnullary nonrecords are encoded in the contents field
@@ -1244,11 +1206,11 @@ instance OVERLAPPING_
1244 ) => ConsFromJSON' arity (S1 s a) True where
1206 ) => ConsFromJSON' arity (S1 s a) True where
1245 consParseJSON' p@(cname :* tname :* opts :* fargs)
1207 consParseJSON' p@(cname :* tname :* opts :* fargs)
1246 | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
1208 | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
1247− | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1209+ | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON p)
1249instance RecordFromJSON arity f => ConsFromJSON' arity f True where
1211instance RecordFromJSON arity f => ConsFromJSON' arity f True where
1250 consParseJSON' p@(cname :* tname :* _) =
1212 consParseJSON' p@(cname :* tname :* _) =
1251− Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1213+ Tagged . withObject (showCons cname tname) (recordParseJSON p)
1253instance OVERLAPPING_
1215instance OVERLAPPING_
1254 ConsFromJSON' arity U1 False where
1216 ConsFromJSON' arity U1 False where
@@ -1274,55 +1236,21 @@ instance (ProductFromJSON arity f, ProductSize f
1275--------------------------------------------------------------------------------
1237--------------------------------------------------------------------------------
1277−class FieldNames f where
1278− fieldNames :: f a -> [Text] -> [Text]
1280−instance (FieldNames a, FieldNames b) => FieldNames (a :*: b) where
1282− fieldNames (undefined :: a x) .
1283− fieldNames (undefined :: b y)
1285−instance (Selector s) => FieldNames (S1 s f) where
1286− fieldNames _ = (pack (selName (undefined :: M1 _i s _f _p)) :)
1288class RecordFromJSON arity f where
1239class RecordFromJSON arity f where
1289 recordParseJSON
1240 recordParseJSON
1290− :: Bool :* ConName :* TypeName :* Options :* FromArgs arity a
1291− -> Object -> Parser (f a)
1293−instance ( FieldNames f
1294− , RecordFromJSON' arity f
1295− ) => RecordFromJSON arity f where
1296− recordParseJSON (fromTaggedSum :* p@(cname :* tname :* opts :* _)) =
1297− \obj -> checkUnknown obj >> recordParseJSON' p obj
1299− knownFields :: H.HashMap Text ()
1300− knownFields = H.fromList $ map (,()) $
1301− fieldNames (undefined :: f a)
1302− [pack (tagFieldName (sumEncoding opts)) | fromTaggedSum]
1304− if not (rejectUnknownFields opts)
1305− then \_ -> return ()
1306− else \obj -> case H.keys (H.difference obj knownFields) of
1308− unknownFields -> contextCons cname tname $
1309− fail ("unknown fields: " ++ show unknownFields)
1311−class RecordFromJSON' arity f where
1313 :: ConName :* TypeName :* Options :* FromArgs arity a
1241 :: ConName :* TypeName :* Options :* FromArgs arity a
1314 -> Object -> Parser (f a)
1242 -> Object -> Parser (f a)
1316−instance ( RecordFromJSON' arity a
1244+instance ( RecordFromJSON arity a
1317− , RecordFromJSON' arity b
1245+ , RecordFromJSON arity b
1318− ) => RecordFromJSON' arity (a :*: b) where
1246+ ) => RecordFromJSON arity (a :*: b) where
1319− recordParseJSON' p obj =
1247+ recordParseJSON p obj =
1320− (:*:) <$> recordParseJSON' p obj
1248+ (:*:) <$> recordParseJSON p obj
1321− <*> recordParseJSON' p obj
1249+ <*> recordParseJSON p obj
1323instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1251instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1324− RecordFromJSON' arity (S1 s a) where
1252+ RecordFromJSON arity (S1 s a) where
1325− recordParseJSON' (cname :* tname :* opts :* fargs) obj = do
1253+ recordParseJSON (cname :* tname :* opts :* fargs) obj = do
1326 fv <- contextCons cname tname (obj .: label)
1254 fv <- contextCons cname tname (obj .: label)
1327 M1 <$> gParseJSON opts fargs fv <?> Key label
1255 M1 <$> gParseJSON opts fargs fv <?> Key label
@@ -1330,16 +1258,16 @@ instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1330 sname = selName (undefined :: M1 _i s _f _p)
1258 sname = selName (undefined :: M1 _i s _f _p)
1332instance INCOHERENT_ (Selector s, FromJSON a) =>
1260instance INCOHERENT_ (Selector s, FromJSON a) =>
1333− RecordFromJSON' arity (S1 s (K1 i (Maybe a))) where
1261+ RecordFromJSON arity (S1 s (K1 i (Maybe a))) where
1334− recordParseJSON' (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
1262+ recordParseJSON (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
1336 label = fieldLabelModifier opts sname
1264 label = fieldLabelModifier opts sname
1337 sname = selName (undefined :: M1 _i s _f _p)
1265 sname = selName (undefined :: M1 _i s _f _p)
1339-- Parse an Option like a Maybe.
1267-- Parse an Option like a Maybe.
1340instance INCOHERENT_ (Selector s, FromJSON a) =>
1268instance INCOHERENT_ (Selector s, FromJSON a) =>
1341− RecordFromJSON' arity (S1 s (K1 i (Semigroup.Option a))) where
1269+ RecordFromJSON arity (S1 s (K1 i (Semigroup.Option a))) where
1342− recordParseJSON' p obj = wrap <$> recordParseJSON' p obj
1270+ recordParseJSON p obj = wrap <$> recordParseJSON p obj
1344 wrap :: S1 s (K1 i (Maybe a)) p -> S1 s (K1 i (Semigroup.Option a)) p
1272 wrap :: S1 s (K1 i (Maybe a)) p -> S1 s (K1 i (Semigroup.Option a)) p
1345 wrap (M1 (K1 a)) = M1 (K1 (Semigroup.Option a))
1273 wrap (M1 (K1 a)) = M1 (K1 (Semigroup.Option a))
@@ -1576,22 +1504,12 @@ instance FromJSONKey Float where
1576 _ -> Scientific.toRealFloat <$> parseScientificText t
1504 _ -> Scientific.toRealFloat <$> parseScientificText t
1578instance (FromJSON a, Integral a) => FromJSON (Ratio a) where
1506instance (FromJSON a, Integral a) => FromJSON (Ratio a) where
1579− parseJSON (Number x)
1581− , exp10 >= -1024 = return $! realToFrac x
1582− | otherwise = prependContext "Ratio" $ fail msg
1584− exp10 = base10Exponent x
1585− msg = "found a number with exponent " ++ show exp10
1586− ++ ", but it must not be greater than 1024 or less than -1024"
1587− parseJSON o = objParser o
1589− objParser = withObject "Rational" $ \obj -> do
1507+ parseJSON = withObject "Rational" $ \obj -> do
1590− numerator <- obj .: "numerator"
1508+ numerator <- obj .: "numerator"
1591− denominator <- obj .: "denominator"
1509+ denominator <- obj .: "denominator"
1592− if denominator == 0
1510+ if denominator == 0
1593− then fail "Ratio denominator was 0"
1511+ then fail "Ratio denominator was 0"
1594− else pure $ numerator % denominator
1512+ else pure $ numerator % denominator
1595 {-# INLINE parseJSON #-}
1513 {-# INLINE parseJSON #-}
1597-- | This instance includes a bounds check to prevent maliciously
1515-- | This instance includes a bounds check to prevent maliciously
@@ -1742,7 +1660,7 @@ instance FromJSON1 NonEmpty where
1742 liftParseJSON p _ = withArray "NonEmpty" $
1660 liftParseJSON p _ = withArray "NonEmpty" $
1743 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1661 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1745− ne [] = fail "parsing NonEmpty failed, unexpected empty list"
1663+ ne [] = fail "parsing NonEmpty failed, unpexpected empty list"
1746 ne (x:xs) = pure (x :| xs)
1664 ne (x:xs) = pure (x :| xs)
1747 {-# INLINE liftParseJSON #-}
1665 {-# INLINE liftParseJSON #-}
@@ -1997,7 +1915,7 @@ instance FromJSON DotNetTime where
1997 parseJSON = withText "DotNetTime" $ \t ->
1915 parseJSON = withText "DotNetTime" $ \t ->
1998 let (s,m) = T.splitAt (T.length t - 5) t
1916 let (s,m) = T.splitAt (T.length t - 5) t
1999 t' = T.concat [s,".",m]
1917 t' = T.concat [s,".",m]
2000− in case parseTimeM True defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
1918+ in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
2001 Just d -> pure (DotNetTime d)
1919 Just d -> pure (DotNetTime d)
2002 _ -> fail "could not parse .NET time"
1920 _ -> fail "could not parse .NET time"
2003 {-# INLINE parseJSON #-}
1921 {-# INLINE parseJSON #-}
@@ -2006,6 +1924,7 @@ instance FromJSON DotNetTime where
2006-- primitive
1924-- primitive
2007-------------------------------------------------------------------------------
1925-------------------------------------------------------------------------------
1927+#if MIN_VERSION_base(4,7,0)
2009instance FromJSON a => FromJSON (PM.Array a) where
1928instance FromJSON a => FromJSON (PM.Array a) where
2010 -- note: we could do better than this if vector exposed the data
1929 -- note: we could do better than this if vector exposed the data
2011 -- constructor in Data.Vector.
1930 -- constructor in Data.Vector.
@@ -2018,7 +1937,6 @@ instance FromJSON a => FromJSON (PM.SmallArray a) where
2018instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
1937instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
2019 parseJSON = fmap Exts.fromList . parseJSON
1938 parseJSON = fmap Exts.fromList . parseJSON
2021−#if !MIN_VERSION_primitive(0,7,0)
2022instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
1940instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
2023 parseJSON = fmap Exts.fromList . parseJSON
1941 parseJSON = fmap Exts.fromList . parseJSON
@@ -2091,40 +2009,6 @@ instance FromJSON DiffTime where
2091 parseJSON = withBoundedScientific "DiffTime" $ pure . realToFrac
2009 parseJSON = withBoundedScientific "DiffTime" $ pure . realToFrac
2092 {-# INLINE parseJSON #-}
2010 {-# INLINE parseJSON #-}
2094−instance FromJSON SystemTime where
2095− parseJSON v = prependContext "SystemTime" $ do
2097− let n' = floor (n * fromInteger (resolution n) :: Nano)
2098− let (secs, nano) = n' `divMod` resolution n
2099− return (MkSystemTime (fromInteger secs) (fromInteger nano))
2101−instance FromJSON CalendarDiffTime where
2102− parseJSON = withObject "CalendarDiffTime" $ \obj -> CalendarDiffTime
2103− <$> obj .: "months"
2106−instance FromJSON CalendarDiffDays where
2107− parseJSON = withObject "CalendarDiffDays" $ \obj -> CalendarDiffDays
2108− <$> obj .: "months"
2111−instance FromJSON DayOfWeek where
2112− parseJSON = withText "DaysOfWeek" parseDayOfWeek
2114−parseDayOfWeek :: T.Text -> Parser DayOfWeek
2115−parseDayOfWeek t = case T.toLower t of
2116− "monday" -> return Monday
2117− "tuesday" -> return Tuesday
2118− "wednesday" -> return Wednesday
2119− "thursday" -> return Thursday
2120− "friday" -> return Friday
2121− "saturday" -> return Saturday
2122− "sunday" -> return Sunday
2123− _ -> fail "Invalid week day"
2125−instance FromJSONKey DayOfWeek where
2126− fromJSONKey = FromJSONKeyTextParser parseDayOfWeek
2128-------------------------------------------------------------------------------
2012-------------------------------------------------------------------------------
2129-- base Monoid/Semigroup
2013-- base Monoid/Semigroup
2130-------------------------------------------------------------------------------
2014-------------------------------------------------------------------------------