@@ -5,16 +5,19 @@
55{-# LANGUAGE FlexibleInstances #-}
66{-# LANGUAGE GADTs #-}
77{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE NamedFieldPuns #-}
89{-# LANGUAGE NoImplicitPrelude #-}
910{-# LANGUAGE OverloadedStrings #-}
10−{-# LANGUAGE PolyKinds #-}
1111{-# LANGUAGE RecordWildCards #-}
1212{-# LANGUAGE ScopedTypeVariables #-}
1313{-# LANGUAGE TypeOperators #-}
14−{-# LANGUAGE TupleSections #-}
1514{-# LANGUAGE UndecidableInstances #-}
1615{-# LANGUAGE ViewPatterns #-}
1716
17+#if __GLASGOW_HASKELL__ >= 706
18+{-# LANGUAGE PolyKinds #-}
19+#endif
20+
1821#include "incoherent-compat.h"
1922#include "overlapping-compat.h"
2023
@@ -42,9 +45,6 @@ module Data.Aeson.Types.FromJSON
4245 , coerceFromJSONKeyFunction
4346 , mapFromJSONKeyFunction
4447
45− , GFromJSONKey()
46− , genericFromJSONKey
47−
4848 -- * List functions
4949 , listParser
5050
@@ -118,9 +118,9 @@ import GHC.Generics
118118import Numeric.Natural (Natural)
119119import Text.ParserCombinators.ReadP (readP_to_S)
120120import Unsafe.Coerce (unsafeCoerce)
121+import qualified Data.Aeson.Compat as Compat
121122import qualified Data.Aeson.Parser.Time as Time
122123import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
123−import qualified Data.ByteString.Lazy as L
124124import qualified Data.DList as DList
125125import qualified Data.HashMap.Strict as H
126126import qualified Data.HashSet as HashSet
@@ -155,8 +155,18 @@ import qualified Data.Primitive.UnliftedArray as PM
155155import qualified Data.Primitive.PrimArray as PM
156156#endif
157157
158+#ifndef HAS_COERCIBLE
159+#define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 707)
160+#endif
158161
162+#if HAS_COERCIBLE
159163import Data.Coerce (Coercible, coerce)
164+coerce' :: Coercible a b => a -> b
165+coerce' = coerce
166+#else
167+coerce' :: a -> b
168+coerce' = unsafeCoerce
169+#endif
160170
161171parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
162172parseIndexedJSON p idx value = p value <?> Index idx
@@ -396,16 +406,6 @@ class FromJSON a where
396406-- > newtype SomeId = SomeId { getSomeId :: Text }
397407-- > deriving (Eq,Ord,Hashable,FromJSONKey)
398408--
399−-- If you have a sum of nullary constructors, you may use the generic
400−-- implementation:
401−--
402−-- @
403−-- data Color = Red | Green | Blue
404−-- deriving Generic
405−--
406−-- instance 'FromJSONKey' Color where
407−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
408−-- @
409409class FromJSONKey a where
410410 -- | Strategy for parsing the key of a map-like container.
411411 fromJSONKey :: FromJSONKeyFunction a
@@ -428,7 +428,11 @@ class FromJSONKey a where
428428-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
429429-- can be inspected, but cannot be constructed.
430430data CoerceText a where
431+#if HAS_COERCIBLE
431432 CoerceText :: Coercible Text a => CoerceText a
433+#else
434+ CoerceText :: CoerceText a
435+#endif
432436
433437-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
434438-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
@@ -448,7 +452,7 @@ data FromJSONKeyFunction a
448452
449453-- | Only law abiding up to interpretation
450454instance Functor FromJSONKeyFunction where
451− fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce)
455+ fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
452456 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
453457 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
454458 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
@@ -462,7 +466,9 @@ instance Functor FromJSONKeyFunction where
462466--
463467-- On pre GHC 7.8 this is unconstrainted function.
464468fromJSONKeyCoerce ::
469+#if HAS_COERCIBLE
465470 Coercible Text a =>
471+#endif
466472 FromJSONKeyFunction a
467473fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
468474
@@ -470,52 +476,34 @@ fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
470476--
471477-- See note on 'fromJSONKeyCoerce'.
472478coerceFromJSONKeyFunction ::
479+#if HAS_COERCIBLE
473480 Coercible a b =>
481+#endif
474482 FromJSONKeyFunction a -> FromJSONKeyFunction b
483+#if HAS_COERCIBLE
475484coerceFromJSONKeyFunction = coerce
485+#else
486+coerceFromJSONKeyFunction (FromJSONKeyCoerce CoerceText) = FromJSONKeyCoerce CoerceText
487+coerceFromJSONKeyFunction (FromJSONKeyText f) = FromJSONKeyText (coerce' . f)
488+coerceFromJSONKeyFunction (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap coerce' . f)
489+coerceFromJSONKeyFunction (FromJSONKeyValue f) = FromJSONKeyValue (fmap coerce' . f)
490+#endif
476491
477492{-# RULES
478493 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
479494 fmap id x = x
480495 #-}
496+#if HAS_COERCIBLE
481497{-# RULES
482498 "FromJSONKeyCoerce: fmap coerce" forall x .
483499 fmap coerce x = coerceFromJSONKeyFunction x
484500 #-}
501+#endif
485502
486503-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
487504mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
488505mapFromJSONKeyFunction = fmap
489506
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.
493−--
494−-- See also 'genericToJSONKey'.
495−--
496−-- === __Example__
497−--
498−-- @
499−-- data Color = Red | Green | Blue
500−-- deriving 'Generic'
501−--
502−-- instance 'FromJSONKey' Color where
503−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
504−-- @
505−genericFromJSONKey :: forall a. (Generic a, GFromJSONKey (Rep a))
506− => JSONKeyOptions
507− -> FromJSONKeyFunction a
508−genericFromJSONKey opts = FromJSONKeyTextParser $ \t ->
509− case parseSumFromString (keyModifier opts) t of
510− Nothing -> fail $
511− "invalid key " ++ show t ++ ", expected one of " ++ show cnames
512− Just k -> pure (to k)
513− where
514− cnames = unTagged2 (constructorTags (keyModifier opts) :: Tagged2 (Rep a) [String])
515−
516−class (ConstructorNames f, SumFromString f) => GFromJSONKey f where
517−instance (ConstructorNames f, SumFromString f) => GFromJSONKey f where
518−
519507-------------------------------------------------------------------------------
520508-- Functions needed for documentation
521509-------------------------------------------------------------------------------
@@ -676,6 +664,7 @@ instance (FromJSON a) => FromJSON [a] where
676664prependContext :: String -> Parser a -> Parser a
677665prependContext name = prependFailure ("parsing " ++ name ++ " failed, ")
678666
667+
679668-- | @'withObject' name f value@ applies @f@ to the 'Object' when @value@
680669-- is an 'Data.Aeson.Object' and fails otherwise.
681670--
@@ -768,13 +757,13 @@ withBoundedScientific' f v = withBoundedScientific_ id f v
768757-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
769758-- to the 'Parser' in case of failure.
770759withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
771−withBoundedScientific_ whenFail f (Number scientific) =
772− if exp10 > 1024
760+withBoundedScientific_ whenFail f v@(Number scientific) =
761+ if exponent > 1024
773762 then whenFail (fail msg)
774763 else f scientific
775764 where
776− exp10 = base10Exponent scientific
777− msg = "found a number with exponent " ++ show exp10 ++ ", but it must not be greater than 1024"
765+ exponent = base10Exponent scientific
766+ msg = "found a number with exponent " ++ show exponent ++ ", but it must not be greater than 1024"
778767withBoundedScientific_ whenFail _ v =
779768 whenFail (typeMismatch "Number" v)
780769{-# INLINE withBoundedScientific_ #-}
@@ -794,7 +783,7 @@ withBool name _ v = prependContext name (typeMismatch "Boolean" v)
794783-- | Decode a nested JSON-encoded string.
795784withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
796785withEmbeddedJSON _ innerParser (String txt) =
797− either fail innerParser $ eitherDecode (L.fromStrict $ T.encodeUtf8 txt)
786+ either fail innerParser $ eitherDecode (Compat.fromStrict $ T.encodeUtf8 txt)
798787 where
799788 eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
800789 eitherFormatError = either (Left . uncurry formatError) Right
@@ -863,7 +852,7 @@ parseFieldMaybe' = (.:!)
863852-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
864853explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
865854explicitParseField p obj key = case H.lookup key obj of
866− Nothing -> fail $ "key " ++ show key ++ " not found"
855+ Nothing -> fail $ "key " ++ show key ++ " not present"
867856 Just v -> p v <?> Key key
868857{-# INLINE explicitParseField #-}
869858
@@ -922,6 +911,8 @@ type ConName = String
922911contextType :: TypeName -> Parser a -> Parser a
923912contextType = prependContext
924913
914+
915+
925916-- | Add the tagKey that will be looked up while building an ADT
926917-- | Produce the error equivalent to
927918-- | Left "Error in $: parsing T failed, expected an object with keys "tag" and
@@ -929,8 +920,9 @@ contextType = prependContext
929920-- | The parser returned error was: could not find key "tag"
930921contextTag :: Text -> [String] -> Parser a -> Parser a
931922contextTag tagKey cnames = prependFailure
932− ("expected Object with key \"" ++ unpack tagKey ++ "\"" ++
933− " containing one of " ++ show cnames ++ ", ")
923+ ("expected an object with key \"" ++ unpack tagKey ++
924+ "\" where \"tag\" is associated to one of " ++ show cnames ++
925+ ". The parser returned error was: ")
934926
935927-- | Add the name of the constructor being parsed to a parser's error messages.
936928contextCons :: ConName -> TypeName -> Parser a -> Parser a
@@ -1042,46 +1034,41 @@ parseAllNullarySum :: (SumFromString f, ConstructorNames f)
10421034parseAllNullarySum tname opts =
10431035 withText tname $ \tag ->
10441036 maybe (badTag tag) return $
1045− parseSumFromString modifier tag
1037+ parseSumFromString opts tag
10461038 where
1047− badTag tag = failWithCTags tname modifier $ \cnames ->
1039+ badTag tag = failWithCTags tname opts $ \cnames ->
10481040 "expected one of the tags " ++ show cnames ++
10491041 ", but found tag " ++ show tag
1050− modifier = constructorTagModifier opts
10511042
10521043-- | Fail with an informative error message about a mismatched tag.
10531044-- The error message is parameterized by the list of expected tags,
10541045-- to be inferred from the result type of the parser.
10551046failWithCTags
1056− :: forall f a t. ConstructorNames f
1057− => TypeName -> (String -> t) -> ([t] -> String) -> Parser (f a)
1058−failWithCTags tname modifier f =
1047+ :: forall f a. ConstructorNames f
1048+ => TypeName -> Options -> ([String] -> String) -> Parser (f a)
1049+failWithCTags tname opts f =
10591050 contextType tname . fail $ f cnames
10601051 where
1061− cnames = unTagged2 (constructorTags modifier :: Tagged2 f [t])
1052+ cnames = unTagged2 (constructorTags opts :: Tagged2 f [String])
10621053
10631054class SumFromString f where
1064− parseSumFromString :: (String -> String) -> Text -> Maybe (f a)
1055+ parseSumFromString :: Options -> Text -> Maybe (f a)
10651056
10661057instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
10671058 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
10681059 (R1 <$> parseSumFromString opts key)
10691060
10701061instance (Constructor c) => SumFromString (C1 c U1) where
1071− parseSumFromString modifier key
1072− | key == name = Just $ M1 U1
1073− | otherwise = Nothing
1074− where
1075− name = pack $ modifier $ conName (undefined :: M1 _i c _f _p)
1076−
1077−-- For genericFromJSONKey
1078−instance SumFromString a => SumFromString (D1 d a) where
1079− parseSumFromString modifier key = M1 <$> parseSumFromString modifier key
1062+ parseSumFromString opts key | key == name = Just $ M1 U1
1063+ | otherwise = Nothing
1064+ where
1065+ name = pack $ constructorTagModifier opts $
1066+ conName (undefined :: M1 _i c _f _p)
10801067
10811068-- | List of all constructor tags.
1082−constructorTags :: ConstructorNames a => (String -> t) -> Tagged2 a [t]
1083−constructorTags modifier =
1084− fmap DList.toList (constructorNames' modifier)
1069+constructorTags :: ConstructorNames a => Options -> Tagged2 a [String]
1070+constructorTags opts =
1071+ fmap DList.toList (constructorNames' (constructorTagModifier opts))
10851072
10861073-- | List of all constructor names of an ADT, after a given conversion
10871074-- function. (Better inlining.)
@@ -1102,12 +1089,6 @@ instance Constructor c => ConstructorNames (C1 c a) where
11021089 where
11031090 cname = conName (undefined :: M1 _i c _f _p)
11041091
1105−-- For genericFromJSONKey
1106−instance ConstructorNames a => ConstructorNames (D1 d a) where
1107− constructorNames' = retag . constructorNames'
1108− where
1109− retag :: Tagged2 a u -> Tagged2 (D1 d a) u
1110− retag (Tagged2 x) = Tagged2 x
11111092
11121093--------------------------------------------------------------------------------
11131094parseNonAllNullarySum :: forall f c arity.
@@ -1121,15 +1102,17 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
11211102 case sumEncoding opts of
11221103 TaggedObject{..} ->
11231104 withObject tname $ \obj -> do
1124− tag <- contextType tname . contextTag tagKey cnames_ $ obj .: tagKey
1105+ tag <- (contextType tname) . (contextTag tagKey cnames_) $ obj .: tagKey
11251106 fromMaybe (badTag tag <?> Key tagKey) $
1126− parseFromTaggedObject (tag :* contentsFieldName :* p) obj
1107+ parseFromTaggedObject (tag :* contentsFieldName :* p) obj
11271108 where
11281109 tagKey = pack tagFieldName
11291110 badTag tag = failWith_ $ \cnames ->
11301111 "expected tag field to be one of " ++ show cnames ++
11311112 ", but found tag " ++ show tag
1132− cnames_ = unTagged2 (constructorTags (constructorTagModifier opts) :: Tagged2 f [String])
1113+ cnames_ = unTagged2 (constructorTags opts :: Tagged2 f [String])
1114+ --cname_ = conName (undefined :: M1 _i c _f _p)
1115+ -- forall f a. ConstructorNames f
11331116
11341117 ObjectWithSingleField ->
11351118 withObject tname $ \obj -> case H.toList obj of
@@ -1161,7 +1144,7 @@ parseNonAllNullarySum p@(tname :* opts :* _) =
11611144
11621145 UntaggedValue -> parseUntaggedValue p
11631146 where
1164− failWith_ = failWithCTags tname (constructorTagModifier opts)
1147+ failWith_ = failWithCTags tname opts
11651148
11661149--------------------------------------------------------------------------------
11671150
@@ -1201,9 +1184,9 @@ class FromTaggedObject' arity f isRecord where
12011184 :: String :* ConName :* TypeName :* Options :* FromArgs arity a
12021185 -> Object -> Tagged isRecord (Parser (f a))
12031186
1204−instance (RecordFromJSON arity f, FieldNames f) => FromTaggedObject' arity f True where
1187+instance (RecordFromJSON arity f) => FromTaggedObject' arity f True where
12051188 -- Records are unpacked in the tagged object
1206− parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON (True :* p)
1189+ parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON p
12071190
12081191instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
12091192 -- Nonnullary nonrecords are encoded in the contents field
@@ -1244,11 +1227,11 @@ instance OVERLAPPING_
12441227 ) => ConsFromJSON' arity (S1 s a) True where
12451228 consParseJSON' p@(cname :* tname :* opts :* fargs)
12461229 | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
1247− | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1230+ | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON p)
12481231
12491232instance RecordFromJSON arity f => ConsFromJSON' arity f True where
12501233 consParseJSON' p@(cname :* tname :* _) =
1251− Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
1234+ Tagged . withObject (showCons cname tname) (recordParseJSON p)
12521235
12531236instance OVERLAPPING_
12541237 ConsFromJSON' arity U1 False where
@@ -1274,55 +1257,21 @@ instance (ProductFromJSON arity f, ProductSize f
12741257
12751258--------------------------------------------------------------------------------
12761259
1277−class FieldNames f where
1278− fieldNames :: f a -> [Text] -> [Text]
1279−
1280−instance (FieldNames a, FieldNames b) => FieldNames (a :*: b) where
1281− fieldNames _ =
1282− fieldNames (undefined :: a x) .
1283− fieldNames (undefined :: b y)
1284−
1285−instance (Selector s) => FieldNames (S1 s f) where
1286− fieldNames _ = (pack (selName (undefined :: M1 _i s _f _p)) :)
1287−
12881260class RecordFromJSON arity f where
12891261 recordParseJSON
1290− :: Bool :* ConName :* TypeName :* Options :* FromArgs arity a
1291− -> Object -> Parser (f a)
1292−
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
1298− where
1299− knownFields :: H.HashMap Text ()
1300− knownFields = H.fromList $ map (,()) $
1301− fieldNames (undefined :: f a)
1302− [pack (tagFieldName (sumEncoding opts)) | fromTaggedSum]
1303− checkUnknown =
1304− if not (rejectUnknownFields opts)
1305− then \_ -> return ()
1306− else \obj -> case H.keys (H.difference obj knownFields) of
1307− [] -> return ()
1308− unknownFields -> contextCons cname tname $
1309− fail ("unknown fields: " ++ show unknownFields)
1310−
1311−class RecordFromJSON' arity f where
1312− recordParseJSON'
13131262 :: ConName :* TypeName :* Options :* FromArgs arity a
13141263 -> Object -> Parser (f a)
13151264
1316−instance ( RecordFromJSON' arity a
1317− , RecordFromJSON' arity b
1318− ) => RecordFromJSON' arity (a :*: b) where
1319− recordParseJSON' p obj =
1320− (:*:) <$> recordParseJSON' p obj
1321− <*> recordParseJSON' p obj
1265+instance ( RecordFromJSON arity a
1266+ , RecordFromJSON arity b
1267+ ) => RecordFromJSON arity (a :*: b) where
1268+ recordParseJSON p obj =
1269+ (:*:) <$> recordParseJSON p obj
1270+ <*> recordParseJSON p obj
13221271
13231272instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1324− RecordFromJSON' arity (S1 s a) where
1325− recordParseJSON' (cname :* tname :* opts :* fargs) obj = do
1273+ RecordFromJSON arity (S1 s a) where
1274+ recordParseJSON (cname :* tname :* opts :* fargs) obj = do
13261275 fv <- contextCons cname tname (obj .: label)
13271276 M1 <$> gParseJSON opts fargs fv <?> Key label
13281277 where
@@ -1330,16 +1279,16 @@ instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
13301279 sname = selName (undefined :: M1 _i s _f _p)
13311280
13321281instance INCOHERENT_ (Selector s, FromJSON a) =>
1333− RecordFromJSON' arity (S1 s (K1 i (Maybe a))) where
1334− recordParseJSON' (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
1282+ RecordFromJSON arity (S1 s (K1 i (Maybe a))) where
1283+ recordParseJSON (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
13351284 where
13361285 label = fieldLabelModifier opts sname
13371286 sname = selName (undefined :: M1 _i s _f _p)
13381287
13391288-- Parse an Option like a Maybe.
13401289instance INCOHERENT_ (Selector s, FromJSON a) =>
1341− RecordFromJSON' arity (S1 s (K1 i (Semigroup.Option a))) where
1342− recordParseJSON' p obj = wrap <$> recordParseJSON' p obj
1290+ RecordFromJSON arity (S1 s (K1 i (Semigroup.Option a))) where
1291+ recordParseJSON p obj = wrap <$> recordParseJSON p obj
13431292 where
13441293 wrap :: S1 s (K1 i (Maybe a)) p -> S1 s (K1 i (Semigroup.Option a)) p
13451294 wrap (M1 (K1 a)) = M1 (K1 (Semigroup.Option a))
@@ -1576,22 +1525,12 @@ instance FromJSONKey Float where
15761525 _ -> Scientific.toRealFloat <$> parseScientificText t
15771526
15781527instance (FromJSON a, Integral a) => FromJSON (Ratio a) where
1579− parseJSON (Number x)
1580− | exp10 <= 1024
1581− , exp10 >= -1024 = return $! realToFrac x
1582− | otherwise = prependContext "Ratio" $ fail msg
1583− where
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
1588− where
1589− objParser = withObject "Rational" $ \obj -> do
1590− numerator <- obj .: "numerator"
1591− denominator <- obj .: "denominator"
1592− if denominator == 0
1593− then fail "Ratio denominator was 0"
1594− else pure $ numerator % denominator
1528+ parseJSON = withObject "Rational" $ \obj -> do
1529+ numerator <- obj .: "numerator"
1530+ denominator <- obj .: "denominator"
1531+ if denominator == 0
1532+ then fail "Ratio denominator was 0"
1533+ else pure $ numerator % denominator
15951534 {-# INLINE parseJSON #-}
15961535
15971536-- | This instance includes a bounds check to prevent maliciously
@@ -2006,6 +1945,7 @@ instance FromJSON DotNetTime where
20061945-- primitive
20071946-------------------------------------------------------------------------------
20081947
1948+#if MIN_VERSION_base(4,7,0)
20091949instance FromJSON a => FromJSON (PM.Array a) where
20101950 -- note: we could do better than this if vector exposed the data
20111951 -- constructor in Data.Vector.
@@ -2023,6 +1963,7 @@ instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
20231963 parseJSON = fmap Exts.fromList . parseJSON
20241964#endif
20251965#endif
1966+#endif
20261967
20271968-------------------------------------------------------------------------------
20281969-- time