@@ -5,16 +5,19 @@
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 #-}
15{-# LANGUAGE UndecidableInstances #-}
14{-# LANGUAGE UndecidableInstances #-}
16{-# LANGUAGE ViewPatterns #-}
15{-# LANGUAGE ViewPatterns #-}
17+#if __GLASGOW_HASKELL__ >= 706
18+{-# LANGUAGE PolyKinds #-}
18#include "incoherent-compat.h"
21#include "incoherent-compat.h"
19#include "overlapping-compat.h"
22#include "overlapping-compat.h"
@@ -42,9 +45,6 @@ module Data.Aeson.Types.FromJSON
42 , coerceFromJSONKeyFunction
45 , coerceFromJSONKeyFunction
43 , mapFromJSONKeyFunction
46 , mapFromJSONKeyFunction
48 -- * List functions
48 -- * List functions
49 , listParser
49 , listParser
@@ -87,7 +87,7 @@ import Data.Aeson.Parser.Internal (eitherDecodeWith, jsonEOF)
87import Data.Aeson.Types.Generic
87import Data.Aeson.Types.Generic
88import Data.Aeson.Types.Internal
88import Data.Aeson.Types.Internal
89import Data.Bits (unsafeShiftR)
89import Data.Bits (unsafeShiftR)
90−import Data.Fixed (Fixed, HasResolution (resolution), Nano)
90+import Data.Fixed (Fixed, HasResolution)
91import Data.Functor.Compose (Compose(..))
91import Data.Functor.Compose (Compose(..))
92import Data.Functor.Identity (Identity(..))
92import Data.Functor.Identity (Identity(..))
93import Data.Functor.Product (Product(..))
93import Data.Functor.Product (Product(..))
@@ -103,10 +103,8 @@ import Data.Scientific (Scientific, base10Exponent)
103import Data.Tagged (Tagged(..))
103import Data.Tagged (Tagged(..))
104import Data.Text (Text, pack, unpack)
104import Data.Text (Text, pack, unpack)
105import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
105import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
106−import Data.Time.Calendar.Compat (CalendarDiffDays (..), DayOfWeek (..))
106+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)
107+import Data.Time.Locale.Compat (defaultTimeLocale)
110import Data.Traversable as Tr (sequence)
108import Data.Traversable as Tr (sequence)
111import Data.Vector (Vector)
109import Data.Vector (Vector)
112import Data.Version (Version, parseVersion)
110import Data.Version (Version, parseVersion)
@@ -118,9 +116,9 @@ import GHC.Generics
118import Numeric.Natural (Natural)
116import Numeric.Natural (Natural)
119import Text.ParserCombinators.ReadP (readP_to_S)
117import Text.ParserCombinators.ReadP (readP_to_S)
120import Unsafe.Coerce (unsafeCoerce)
118import Unsafe.Coerce (unsafeCoerce)
119+import qualified Data.Aeson.Compat as Compat
121import qualified Data.Aeson.Parser.Time as Time
120import qualified Data.Aeson.Parser.Time as Time
122import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
121import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
123−import qualified Data.ByteString.Lazy as L
124import qualified Data.DList as DList
122import qualified Data.DList as DList
125import qualified Data.HashMap.Strict as H
123import qualified Data.HashMap.Strict as H
126import qualified Data.HashSet as HashSet
124import qualified Data.HashSet as HashSet
@@ -149,14 +147,22 @@ import qualified Data.Primitive.SmallArray as PM
149import qualified Data.Primitive.Types as PM
147import qualified Data.Primitive.Types as PM
151#if MIN_VERSION_primitive(0,6,4)
149#if MIN_VERSION_primitive(0,6,4)
152−#if !MIN_VERSION_primitive(0,7,0)
153import qualified Data.Primitive.UnliftedArray as PM
150import qualified Data.Primitive.UnliftedArray as PM
155import qualified Data.Primitive.PrimArray as PM
151import qualified Data.Primitive.PrimArray as PM
154+#ifndef HAS_COERCIBLE
155+#define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 707)
159import Data.Coerce (Coercible, coerce)
159import Data.Coerce (Coercible, coerce)
160+coerce' :: Coercible a b => a -> b
164+coerce' = unsafeCoerce
161parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
167parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
162parseIndexedJSON p idx value = p value <?> Index idx
168parseIndexedJSON p idx value = p value <?> Index idx
@@ -396,16 +402,6 @@ class FromJSON a where
396-- > newtype SomeId = SomeId { getSomeId :: Text }
402-- > newtype SomeId = SomeId { getSomeId :: Text }
397-- > deriving (Eq,Ord,Hashable,FromJSONKey)
403-- > 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
405class FromJSONKey a where
410 -- | Strategy for parsing the key of a map-like container.
406 -- | Strategy for parsing the key of a map-like container.
411 fromJSONKey :: FromJSONKeyFunction a
407 fromJSONKey :: FromJSONKeyFunction a
@@ -428,7 +424,11 @@ class FromJSONKey a where
428-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
424-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
429-- can be inspected, but cannot be constructed.
425-- can be inspected, but cannot be constructed.
430data CoerceText a where
426data CoerceText a where
431 CoerceText :: Coercible Text a => CoerceText a
428 CoerceText :: Coercible Text a => CoerceText a
430+ CoerceText :: CoerceText a
433-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
433-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
434-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
434-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
@@ -448,7 +448,7 @@ data FromJSONKeyFunction a
449-- | Only law abiding up to interpretation
449-- | Only law abiding up to interpretation
450instance Functor FromJSONKeyFunction where
450instance Functor FromJSONKeyFunction where
451− fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce)
451+ fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
452 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
452 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
453 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
453 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
454 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
454 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
@@ -462,7 +462,9 @@ instance Functor FromJSONKeyFunction where
463-- On pre GHC 7.8 this is unconstrainted function.
463-- On pre GHC 7.8 this is unconstrainted function.
464fromJSONKeyCoerce ::
464fromJSONKeyCoerce ::
465 Coercible Text a =>
466 Coercible Text a =>
466 FromJSONKeyFunction a
468 FromJSONKeyFunction a
467fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
469fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
@@ -470,52 +472,34 @@ fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
471-- See note on 'fromJSONKeyCoerce'.
473-- See note on 'fromJSONKeyCoerce'.
472coerceFromJSONKeyFunction ::
474coerceFromJSONKeyFunction ::
473 Coercible a b =>
476 Coercible a b =>
474 FromJSONKeyFunction a -> FromJSONKeyFunction b
478 FromJSONKeyFunction a -> FromJSONKeyFunction b
475coerceFromJSONKeyFunction = coerce
480coerceFromJSONKeyFunction = coerce
482+coerceFromJSONKeyFunction (FromJSONKeyCoerce CoerceText) = FromJSONKeyCoerce CoerceText
483+coerceFromJSONKeyFunction (FromJSONKeyText f) = FromJSONKeyText (coerce' . f)
484+coerceFromJSONKeyFunction (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap coerce' . f)
485+coerceFromJSONKeyFunction (FromJSONKeyValue f) = FromJSONKeyValue (fmap coerce' . f)
478 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
489 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
479 fmap id x = x
490 fmap id x = x
482 "FromJSONKeyCoerce: fmap coerce" forall x .
494 "FromJSONKeyCoerce: fmap coerce" forall x .
483 fmap coerce x = coerceFromJSONKeyFunction x
495 fmap coerce x = coerceFromJSONKeyFunction x
486-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
499-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
487mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
500mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
488mapFromJSONKeyFunction = fmap
501mapFromJSONKeyFunction = 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-------------------------------------------------------------------------------
503-------------------------------------------------------------------------------
520-- Functions needed for documentation
504-- Functions needed for documentation
521-------------------------------------------------------------------------------
505-------------------------------------------------------------------------------
@@ -768,13 +752,13 @@ withBoundedScientific' f v = withBoundedScientific_ id f v
768-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
752-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
769-- to the 'Parser' in case of failure.
753-- to the 'Parser' in case of failure.
770withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
754withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
771−withBoundedScientific_ whenFail f (Number scientific) =
755+withBoundedScientific_ whenFail f v@(Number scientific) =
772− if exp10 > 1024
756+ if exponent > 1024
773 then whenFail (fail msg)
757 then whenFail (fail msg)
774 else f scientific
758 else f scientific
776− exp10 = base10Exponent scientific
760+ exponent = base10Exponent scientific
777− msg = "found a number with exponent " ++ show exp10 ++ ", but it must not be greater than 1024"
761+ msg = "found a number with exponent " ++ show exponent ++ ", but it must not be greater than 1024"
778withBoundedScientific_ whenFail _ v =
762withBoundedScientific_ whenFail _ v =
779 whenFail (typeMismatch "Number" v)
763 whenFail (typeMismatch "Number" v)
780{-# INLINE withBoundedScientific_ #-}
764{-# INLINE withBoundedScientific_ #-}
@@ -794,7 +778,7 @@ withBool name _ v = prependContext name (typeMismatch "Boolean" v)
794-- | Decode a nested JSON-encoded string.
778-- | Decode a nested JSON-encoded string.
795withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
779withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
796withEmbeddedJSON _ innerParser (String txt) =
780withEmbeddedJSON _ innerParser (String txt) =
797− either fail innerParser $ eitherDecode (L.fromStrict $ T.encodeUtf8 txt)
781+ either fail innerParser $ eitherDecode (Compat.fromStrict $ T.encodeUtf8 txt)
799 eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
783 eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
800 eitherFormatError = either (Left . uncurry formatError) Right
784 eitherFormatError = either (Left . uncurry formatError) Right
@@ -863,7 +847,7 @@ parseFieldMaybe' = (.:!)
863-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
847-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
864explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
848explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
865explicitParseField p obj key = case H.lookup key obj of
849explicitParseField p obj key = case H.lookup key obj of
866− Nothing -> fail $ "key " ++ show key ++ " not found"
850+ Nothing -> fail $ "key " ++ show key ++ " not present"
867 Just v -> p v <?> Key key
851 Just v -> p v <?> Key key
868{-# INLINE explicitParseField #-}
852{-# INLINE explicitParseField #-}
@@ -922,16 +906,6 @@ type ConName = String
922contextType :: TypeName -> Parser a -> Parser a
906contextType :: TypeName -> Parser a -> Parser a
923contextType = prependContext
907contextType = 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.
909-- | Add the name of the constructor being parsed to a parser's error messages.
936contextCons :: ConName -> TypeName -> Parser a -> Parser a
910contextCons :: ConName -> TypeName -> Parser a -> Parser a
937contextCons cname tname = prependContext (showCons cname tname)
911contextCons cname tname = prependContext (showCons cname tname)
@@ -1042,46 +1016,41 @@ parseAllNullarySum :: (SumFromString f, ConstructorNames f)
1042parseAllNullarySum tname opts =
1016parseAllNullarySum tname opts =
1043 withText tname $ \tag ->
1017 withText tname $ \tag ->
1044 maybe (badTag tag) return $
1018 maybe (badTag tag) return $
1045− parseSumFromString modifier tag
1019+ parseSumFromString opts tag
1047− badTag tag = failWithCTags tname modifier $ \cnames ->
1021+ badTag tag = failWithCTags tname opts $ \cnames ->
1048 "expected one of the tags " ++ show cnames ++
1022 "expected one of the tags " ++ show cnames ++
1049 ", but found tag " ++ show tag
1023 ", but found tag " ++ show tag
1050− modifier = constructorTagModifier opts
1052-- | Fail with an informative error message about a mismatched tag.
1025-- | Fail with an informative error message about a mismatched tag.
1053-- The error message is parameterized by the list of expected tags,
1026-- The error message is parameterized by the list of expected tags,
1054-- to be inferred from the result type of the parser.
1027-- to be inferred from the result type of the parser.
1055failWithCTags
1028failWithCTags
1056− :: forall f a t. ConstructorNames f
1029+ :: forall f a. ConstructorNames f
1057− => TypeName -> (String -> t) -> ([t] -> String) -> Parser (f a)
1030+ => TypeName -> Options -> ([String] -> String) -> Parser (f a)
1058−failWithCTags tname modifier f =
1031+failWithCTags tname opts f =
1059 contextType tname . fail $ f cnames
1032 contextType tname . fail $ f cnames
1061− cnames = unTagged2 (constructorTags modifier :: Tagged2 f [t])
1034+ cnames = unTagged2 (constructorTags opts :: Tagged2 f [String])
1063class SumFromString f where
1036class SumFromString f where
1064− parseSumFromString :: (String -> String) -> Text -> Maybe (f a)
1037+ parseSumFromString :: Options -> Text -> Maybe (f a)
1066instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
1039instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
1067 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
1040 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
1068 (R1 <$> parseSumFromString opts key)
1041 (R1 <$> parseSumFromString opts key)
1070instance (Constructor c) => SumFromString (C1 c U1) where
1043instance (Constructor c) => SumFromString (C1 c U1) where
1071− parseSumFromString modifier key
1044+ parseSumFromString opts key | key == name = Just $ M1 U1
1072− | key == name = Just $ M1 U1
1073− | otherwise = Nothing
1045+ | otherwise = Nothing
1047+ name = pack $ constructorTagModifier opts $
1075− name = pack $ modifier $ conName (undefined :: M1 _i c _f _p)
1048+ 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.
1050-- | List of all constructor tags.
1082−constructorTags :: ConstructorNames a => (String -> t) -> Tagged2 a [t]
1051+constructorTags :: ConstructorNames a => Options -> Tagged2 a [String]
1083−constructorTags modifier =
1052+constructorTags opts =
1084− fmap DList.toList (constructorNames' modifier)
1053+ fmap DList.toList (constructorNames' (constructorTagModifier opts))
1086-- | List of all constructor names of an ADT, after a given conversion
1055-- | List of all constructor names of an ADT, after a given conversion
1087-- function. (Better inlining.)
1056-- function. (Better inlining.)
@@ -1102,16 +1071,9 @@ instance Constructor c => ConstructorNames (C1 c a) where
1103 cname = conName (undefined :: M1 _i c _f _p)
1072 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--------------------------------------------------------------------------------
1074--------------------------------------------------------------------------------
1113−parseNonAllNullarySum :: forall f c arity.
1076+parseNonAllNullarySum :: ( FromPair arity f
1115 , FromTaggedObject arity f
1077 , FromTaggedObject arity f
1116 , FromUntaggedValue arity f
1078 , FromUntaggedValue arity f
1117 , ConstructorNames f
1079 , ConstructorNames f
@@ -1121,7 +1083,7 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1121 case sumEncoding opts of
1083 case sumEncoding opts of
1122 TaggedObject{..} ->
1084 TaggedObject{..} ->
1123 withObject tname $ \obj -> do
1085 withObject tname $ \obj -> do
1124− tag <- contextType tname . contextTag tagKey cnames_ $ obj .: tagKey
1086+ tag <- contextType tname $ obj .: tagKey
1125 fromMaybe (badTag tag <?> Key tagKey) $
1087 fromMaybe (badTag tag <?> Key tagKey) $
1126 parseFromTaggedObject (tag :* contentsFieldName :* p) obj
1088 parseFromTaggedObject (tag :* contentsFieldName :* p) obj
@@ -1129,7 +1091,6 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1129 badTag tag = failWith_ $ \cnames ->
1091 badTag tag = failWith_ $ \cnames ->
1130 "expected tag field to be one of " ++ show cnames ++
1092 "expected tag field to be one of " ++ show cnames ++
1131 ", but found tag " ++ show tag
1093 ", but found tag " ++ show tag
1132− cnames_ = unTagged2 (constructorTags (constructorTagModifier opts) :: Tagged2 f [String])
1134 ObjectWithSingleField ->
1095 ObjectWithSingleField ->
1135 withObject tname $ \obj -> case H.toList obj of
1096 withObject tname $ \obj -> case H.toList obj of
@@ -1161,7 +1122,7 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
1162 UntaggedValue -> parseUntaggedValue p
1123 UntaggedValue -> parseUntaggedValue p
1164− failWith_ = failWithCTags tname (constructorTagModifier opts)
1125+ failWith_ = failWithCTags tname opts
1166--------------------------------------------------------------------------------
1127--------------------------------------------------------------------------------
@@ -1201,9 +1162,9 @@ class FromTaggedObject' arity f isRecord where
1201 :: String :* ConName :* TypeName :* Options :* FromArgs arity a
1162 :: String :* ConName :* TypeName :* Options :* FromArgs arity a
1202 -> Object -> Tagged isRecord (Parser (f a))
1163 -> Object -> Tagged isRecord (Parser (f a))
1204−instance (RecordFromJSON arity f, FieldNames f) => FromTaggedObject' arity f True where
1165+instance (RecordFromJSON arity f) => FromTaggedObject' arity f True where
1205 -- Records are unpacked in the tagged object
1166 -- Records are unpacked in the tagged object
1206− parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON (True :* p)
1167+ parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON p
1208instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
1169instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
1209 -- Nonnullary nonrecords are encoded in the contents field
1170 -- Nonnullary nonrecords are encoded in the contents field
@@ -1244,11 +1205,11 @@ instance OVERLAPPING_
1244 ) => ConsFromJSON' arity (S1 s a) True where
1205 ) => ConsFromJSON' arity (S1 s a) True where
1245 consParseJSON' p@(cname :* tname :* opts :* fargs)
1206 consParseJSON' p@(cname :* tname :* opts :* fargs)
1246 | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
1207 | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
1247− | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1208+ | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON p)
1249instance RecordFromJSON arity f => ConsFromJSON' arity f True where
1210instance RecordFromJSON arity f => ConsFromJSON' arity f True where
1250 consParseJSON' p@(cname :* tname :* _) =
1211 consParseJSON' p@(cname :* tname :* _) =
1251− Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1212+ Tagged . withObject (showCons cname tname) (recordParseJSON p)
1253instance OVERLAPPING_
1214instance OVERLAPPING_
1254 ConsFromJSON' arity U1 False where
1215 ConsFromJSON' arity U1 False where
@@ -1274,55 +1235,21 @@ instance (ProductFromJSON arity f, ProductSize f
1275--------------------------------------------------------------------------------
1236--------------------------------------------------------------------------------
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
1238class RecordFromJSON arity f where
1289 recordParseJSON
1239 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
1240 :: ConName :* TypeName :* Options :* FromArgs arity a
1314 -> Object -> Parser (f a)
1241 -> Object -> Parser (f a)
1316−instance ( RecordFromJSON' arity a
1243+instance ( RecordFromJSON arity a
1317− , RecordFromJSON' arity b
1244+ , RecordFromJSON arity b
1318− ) => RecordFromJSON' arity (a :*: b) where
1245+ ) => RecordFromJSON arity (a :*: b) where
1319− recordParseJSON' p obj =
1246+ recordParseJSON p obj =
1320− (:*:) <$> recordParseJSON' p obj
1247+ (:*:) <$> recordParseJSON p obj
1321− <*> recordParseJSON' p obj
1248+ <*> recordParseJSON p obj
1323instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1250instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1324− RecordFromJSON' arity (S1 s a) where
1251+ RecordFromJSON arity (S1 s a) where
1325− recordParseJSON' (cname :* tname :* opts :* fargs) obj = do
1252+ recordParseJSON (cname :* tname :* opts :* fargs) obj = do
1326 fv <- contextCons cname tname (obj .: label)
1253 fv <- contextCons cname tname (obj .: label)
1327 M1 <$> gParseJSON opts fargs fv <?> Key label
1254 M1 <$> gParseJSON opts fargs fv <?> Key label
@@ -1330,16 +1257,16 @@ instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1330 sname = selName (undefined :: M1 _i s _f _p)
1257 sname = selName (undefined :: M1 _i s _f _p)
1332instance INCOHERENT_ (Selector s, FromJSON a) =>
1259instance INCOHERENT_ (Selector s, FromJSON a) =>
1333− RecordFromJSON' arity (S1 s (K1 i (Maybe a))) where
1260+ RecordFromJSON arity (S1 s (K1 i (Maybe a))) where
1334− recordParseJSON' (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
1261+ recordParseJSON (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
1336 label = fieldLabelModifier opts sname
1263 label = fieldLabelModifier opts sname
1337 sname = selName (undefined :: M1 _i s _f _p)
1264 sname = selName (undefined :: M1 _i s _f _p)
1339-- Parse an Option like a Maybe.
1266-- Parse an Option like a Maybe.
1340instance INCOHERENT_ (Selector s, FromJSON a) =>
1267instance INCOHERENT_ (Selector s, FromJSON a) =>
1341− RecordFromJSON' arity (S1 s (K1 i (Semigroup.Option a))) where
1268+ RecordFromJSON arity (S1 s (K1 i (Semigroup.Option a))) where
1342− recordParseJSON' p obj = wrap <$> recordParseJSON' p obj
1269+ recordParseJSON p obj = wrap <$> recordParseJSON p obj
1344 wrap :: S1 s (K1 i (Maybe a)) p -> S1 s (K1 i (Semigroup.Option a)) p
1271 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))
1272 wrap (M1 (K1 a)) = M1 (K1 (Semigroup.Option a))
@@ -1576,22 +1503,12 @@ instance FromJSONKey Float where
1576 _ -> Scientific.toRealFloat <$> parseScientificText t
1503 _ -> Scientific.toRealFloat <$> parseScientificText t
1578instance (FromJSON a, Integral a) => FromJSON (Ratio a) where
1505instance (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
1506+ parseJSON = withObject "Rational" $ \obj -> do
1590− numerator <- obj .: "numerator"
1507+ numerator <- obj .: "numerator"
1591− denominator <- obj .: "denominator"
1508+ denominator <- obj .: "denominator"
1592− if denominator == 0
1509+ if denominator == 0
1593− then fail "Ratio denominator was 0"
1510+ then fail "Ratio denominator was 0"
1594− else pure $ numerator % denominator
1511+ else pure $ numerator % denominator
1595 {-# INLINE parseJSON #-}
1512 {-# INLINE parseJSON #-}
1597-- | This instance includes a bounds check to prevent maliciously
1514-- | This instance includes a bounds check to prevent maliciously
@@ -1742,7 +1659,7 @@ instance FromJSON1 NonEmpty where
1742 liftParseJSON p _ = withArray "NonEmpty" $
1659 liftParseJSON p _ = withArray "NonEmpty" $
1743 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1660 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1745− ne [] = fail "parsing NonEmpty failed, unexpected empty list"
1662+ ne [] = fail "parsing NonEmpty failed, unpexpected empty list"
1746 ne (x:xs) = pure (x :| xs)
1663 ne (x:xs) = pure (x :| xs)
1747 {-# INLINE liftParseJSON #-}
1664 {-# INLINE liftParseJSON #-}
@@ -1997,7 +1914,7 @@ instance FromJSON DotNetTime where
1997 parseJSON = withText "DotNetTime" $ \t ->
1914 parseJSON = withText "DotNetTime" $ \t ->
1998 let (s,m) = T.splitAt (T.length t - 5) t
1915 let (s,m) = T.splitAt (T.length t - 5) t
1999 t' = T.concat [s,".",m]
1916 t' = T.concat [s,".",m]
2000− in case parseTimeM True defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
1917+ in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
2001 Just d -> pure (DotNetTime d)
1918 Just d -> pure (DotNetTime d)
2002 _ -> fail "could not parse .NET time"
1919 _ -> fail "could not parse .NET time"
2003 {-# INLINE parseJSON #-}
1920 {-# INLINE parseJSON #-}
@@ -2006,6 +1923,7 @@ instance FromJSON DotNetTime where
2006-- primitive
1923-- primitive
2007-------------------------------------------------------------------------------
1924-------------------------------------------------------------------------------
1926+#if MIN_VERSION_base(4,7,0)
2009instance FromJSON a => FromJSON (PM.Array a) where
1927instance FromJSON a => FromJSON (PM.Array a) where
2010 -- note: we could do better than this if vector exposed the data
1928 -- note: we could do better than this if vector exposed the data
2011 -- constructor in Data.Vector.
1929 -- constructor in Data.Vector.
@@ -2018,7 +1936,6 @@ instance FromJSON a => FromJSON (PM.SmallArray a) where
2018instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
1936instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
2019 parseJSON = fmap Exts.fromList . parseJSON
1937 parseJSON = fmap Exts.fromList . parseJSON
2021−#if !MIN_VERSION_primitive(0,7,0)
2022instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
1939instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
2023 parseJSON = fmap Exts.fromList . parseJSON
1940 parseJSON = fmap Exts.fromList . parseJSON
@@ -2091,40 +2008,6 @@ instance FromJSON DiffTime where
2091 parseJSON = withBoundedScientific "DiffTime" $ pure . realToFrac
2008 parseJSON = withBoundedScientific "DiffTime" $ pure . realToFrac
2092 {-# INLINE parseJSON #-}
2009 {-# 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-------------------------------------------------------------------------------
2011-------------------------------------------------------------------------------
2129-- base Monoid/Semigroup
2012-- base Monoid/Semigroup
2130-------------------------------------------------------------------------------
2013-------------------------------------------------------------------------------