packages feed

aeson 0.11.3.0 → 1.0.0.0

raw patch · 69 files changed

+10310/−5015 lines, 69 filesdep +base-compatdep +bytestring-builderdep +generic-derivingdep −mtldep −old-localedep −sybdep ~QuickCheckdep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: base-compat, bytestring-builder, generic-deriving, hashable-time, time-locale-compat, transformers-compat

Dependencies removed: mtl, old-locale, syb

Dependency ranges changed: QuickCheck, base, bytestring, containers, deepseq, dlist, hashable, scientific, semigroups, template-haskell, time, transformers

API changes (from Hackage documentation)

- Data.Aeson: data Encoding
- Data.Aeson.Encode: encodeToBuilder :: Value -> Builder
- Data.Aeson.Encode: fromValue :: Value -> Builder
- Data.Aeson.TH: instance Data.Aeson.Types.Class.FromJSON a => Data.Aeson.TH.LookupField (GHC.Base.Maybe a)
- Data.Aeson.TH: instance Data.Aeson.Types.Class.FromJSON a => Data.Aeson.TH.LookupField a
- Data.Aeson.Types: data Encoding
+ Data.Aeson: FromJSONKeyCoerce :: !(CoerceText a) -> FromJSONKeyFunction a
+ Data.Aeson: FromJSONKeyText :: !(Text -> a) -> FromJSONKeyFunction a
+ Data.Aeson: FromJSONKeyTextParser :: !(Text -> Parser a) -> FromJSONKeyFunction a
+ Data.Aeson: FromJSONKeyValue :: !(Value -> Parser a) -> FromJSONKeyFunction a
+ Data.Aeson: ToJSONKeyText :: !(a -> Text) -> !(a -> Encoding' Text) -> ToJSONKeyFunction a
+ Data.Aeson: ToJSONKeyValue :: !(a -> Value) -> !(a -> Encoding) -> ToJSONKeyFunction a
+ Data.Aeson: [From1Args] :: (Value -> Parser a) -> (Value -> Parser [a]) -> FromArgs One a
+ Data.Aeson: [NoFromArgs] :: FromArgs Zero a
+ Data.Aeson: [NoToArgs] :: ToArgs res Zero a
+ Data.Aeson: [To1Args] :: (a -> res) -> ([a] -> res) -> ToArgs res One a
+ Data.Aeson: class FromJSON1 f where liftParseJSON = genericLiftParseJSON defaultOptions liftParseJSONList f g v = listParser (liftParseJSON f g) v
+ Data.Aeson: class FromJSON2 f where liftParseJSONList2 fa ga fb gb v = case v of { Array vals -> fmap toList (mapM (liftParseJSON2 fa ga fb gb) vals) _ -> typeMismatch "[a]" v }
+ Data.Aeson: class FromJSONKey a where fromJSONKey = FromJSONKeyValue parseJSON fromJSONKeyList = FromJSONKeyValue parseJSON
+ Data.Aeson: class ToJSON1 f where liftToJSON = genericLiftToJSON defaultOptions liftToJSONList f g = listValue (liftToJSON f g) liftToEncoding = genericLiftToEncoding defaultOptions liftToEncodingList f g = listEncoding (liftToEncoding f g)
+ Data.Aeson: class ToJSON2 f where liftToJSONList2 fa ga fb gb = listValue (liftToJSON2 fa ga fb gb) liftToEncodingList2 fa ga fb gb = listEncoding (liftToEncoding2 fa ga fb gb)
+ Data.Aeson: class ToJSONKey a where toJSONKey = ToJSONKeyValue toJSON toEncoding toJSONKeyList = ToJSONKeyValue toJSON toEncoding
+ Data.Aeson: data FromArgs arity a
+ Data.Aeson: data FromJSONKeyFunction a
+ Data.Aeson: data One
+ Data.Aeson: data ToArgs res arity a
+ Data.Aeson: data ToJSONKeyFunction a
+ Data.Aeson: data Zero
+ Data.Aeson: fromJSONKey :: (FromJSONKey a, FromJSON a) => FromJSONKeyFunction a
+ Data.Aeson: fromJSONKeyList :: (FromJSONKey a, FromJSON a) => FromJSONKeyFunction [a]
+ Data.Aeson: genericLiftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f)) => Options -> (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
+ Data.Aeson: genericLiftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f)) => Options -> (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
+ Data.Aeson: genericLiftToJSON :: (Generic1 f, GToJSON One (Rep1 f)) => Options -> (a -> Value) -> ([a] -> Value) -> f a -> Value
+ Data.Aeson: liftParseJSON :: (FromJSON1 f, Generic1 f, GFromJSON One (Rep1 f)) => (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
+ Data.Aeson: liftParseJSON2 :: FromJSON2 f => (Value -> Parser a) -> (Value -> Parser [a]) -> (Value -> Parser b) -> (Value -> Parser [b]) -> Value -> Parser (f a b)
+ Data.Aeson: liftParseJSONList :: FromJSON1 f => (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser [f a]
+ Data.Aeson: liftParseJSONList2 :: FromJSON2 f => (Value -> Parser a) -> (Value -> Parser [a]) -> (Value -> Parser b) -> (Value -> Parser [b]) -> Value -> Parser [f a b]
+ Data.Aeson: liftToEncoding :: (ToJSON1 f, Generic1 f, GToEncoding One (Rep1 f)) => (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
+ Data.Aeson: liftToEncoding2 :: ToJSON2 f => (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> f a b -> Encoding
+ Data.Aeson: liftToEncodingList :: ToJSON1 f => (a -> Encoding) -> ([a] -> Encoding) -> [f a] -> Encoding
+ Data.Aeson: liftToEncodingList2 :: ToJSON2 f => (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> [f a b] -> Encoding
+ Data.Aeson: liftToJSON :: (ToJSON1 f, Generic1 f, GToJSON One (Rep1 f)) => (a -> Value) -> ([a] -> Value) -> f a -> Value
+ Data.Aeson: liftToJSON2 :: ToJSON2 f => (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> f a b -> Value
+ Data.Aeson: liftToJSONList :: ToJSON1 f => (a -> Value) -> ([a] -> Value) -> [f a] -> Value
+ Data.Aeson: liftToJSONList2 :: ToJSON2 f => (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> [f a b] -> Value
+ Data.Aeson: parseJSON1 :: (FromJSON1 f, FromJSON a) => Value -> Parser (f a)
+ Data.Aeson: parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser (f a b)
+ Data.Aeson: parseJSONList :: FromJSON a => Value -> Parser [a]
+ Data.Aeson: toEncoding1 :: (ToJSON1 f, ToJSON a) => f a -> Encoding
+ Data.Aeson: toEncoding2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Encoding
+ Data.Aeson: toEncodingList :: ToJSON a => [a] -> Encoding
+ Data.Aeson: toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value
+ Data.Aeson: toJSON2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Value
+ Data.Aeson: toJSONKey :: (ToJSONKey a, ToJSON a) => ToJSONKeyFunction a
+ Data.Aeson: toJSONKeyList :: (ToJSONKey a, ToJSON a) => ToJSONKeyFunction [a]
+ Data.Aeson: toJSONList :: ToJSON a => [a] -> Value
+ Data.Aeson: type Encoding = Encoding' Value
+ Data.Aeson.Encoding: bool :: Bool -> Encoding
+ Data.Aeson.Encoding: data Encoding' tag
+ Data.Aeson.Encoding: data Series
+ Data.Aeson.Encoding: day :: Day -> Encoding' a
+ Data.Aeson.Encoding: dict :: (k -> Encoding' Text) -> (v -> Encoding) -> (forall a. (k -> v -> a -> a) -> a -> m -> a) -> m -> Encoding
+ Data.Aeson.Encoding: double :: Double -> Encoding
+ Data.Aeson.Encoding: doubleText :: Double -> Encoding' a
+ Data.Aeson.Encoding: emptyArray_ :: Encoding
+ Data.Aeson.Encoding: emptyObject_ :: Encoding
+ Data.Aeson.Encoding: encodingToLazyByteString :: Encoding' a -> ByteString
+ Data.Aeson.Encoding: float :: Float -> Encoding
+ Data.Aeson.Encoding: floatText :: Float -> Encoding' a
+ Data.Aeson.Encoding: fromEncoding :: Encoding' tag -> Builder
+ Data.Aeson.Encoding: int :: Int -> Encoding
+ Data.Aeson.Encoding: int16 :: Int16 -> Encoding
+ Data.Aeson.Encoding: int16Text :: Int16 -> Encoding' a
+ Data.Aeson.Encoding: int32 :: Int32 -> Encoding
+ Data.Aeson.Encoding: int32Text :: Int32 -> Encoding' a
+ Data.Aeson.Encoding: int64 :: Int64 -> Encoding
+ Data.Aeson.Encoding: int64Text :: Int64 -> Encoding' a
+ Data.Aeson.Encoding: int8 :: Int8 -> Encoding
+ Data.Aeson.Encoding: int8Text :: Int8 -> Encoding' a
+ Data.Aeson.Encoding: intText :: Int -> Encoding' a
+ Data.Aeson.Encoding: integer :: Integer -> Encoding
+ Data.Aeson.Encoding: integerText :: Integer -> Encoding' a
+ Data.Aeson.Encoding: lazyText :: Text -> Encoding' a
+ Data.Aeson.Encoding: list :: (a -> Encoding) -> [a] -> Encoding
+ Data.Aeson.Encoding: localTime :: LocalTime -> Encoding' a
+ Data.Aeson.Encoding: nullEncoding :: Encoding' a -> Bool
+ Data.Aeson.Encoding: null_ :: Encoding
+ Data.Aeson.Encoding: pair :: Text -> Encoding -> Series
+ Data.Aeson.Encoding: pairs :: Series -> Encoding
+ Data.Aeson.Encoding: scientific :: Scientific -> Encoding
+ Data.Aeson.Encoding: scientificText :: Scientific -> Encoding' a
+ Data.Aeson.Encoding: string :: String -> Encoding' a
+ Data.Aeson.Encoding: text :: Text -> Encoding' a
+ Data.Aeson.Encoding: timeOfDay :: TimeOfDay -> Encoding' a
+ Data.Aeson.Encoding: type Encoding = Encoding' Value
+ Data.Aeson.Encoding: unsafeToEncoding :: Builder -> Encoding' a
+ Data.Aeson.Encoding: utcTime :: UTCTime -> Encoding' a
+ Data.Aeson.Encoding: value :: Value -> Encoding
+ Data.Aeson.Encoding: word :: Word -> Encoding
+ Data.Aeson.Encoding: word16 :: Word16 -> Encoding
+ Data.Aeson.Encoding: word16Text :: Word16 -> Encoding' a
+ Data.Aeson.Encoding: word32 :: Word32 -> Encoding
+ Data.Aeson.Encoding: word32Text :: Word32 -> Encoding' a
+ Data.Aeson.Encoding: word64 :: Word64 -> Encoding
+ Data.Aeson.Encoding: word64Text :: Word64 -> Encoding' a
+ Data.Aeson.Encoding: word8 :: Word8 -> Encoding
+ Data.Aeson.Encoding: word8Text :: Word8 -> Encoding' a
+ Data.Aeson.Encoding: wordText :: Word -> Encoding' a
+ Data.Aeson.Encoding: zonedTime :: ZonedTime -> Encoding' a
+ Data.Aeson.Encoding.Internal: (>*<) :: Encoding' a -> Encoding' b -> Encoding' InArray
+ Data.Aeson.Encoding.Internal: (><) :: Encoding' a -> Encoding' a -> Encoding' a
+ Data.Aeson.Encoding.Internal: Empty :: Series
+ Data.Aeson.Encoding.Internal: Encoding :: Builder -> Encoding' tag
+ Data.Aeson.Encoding.Internal: Value :: (Encoding' Series) -> Series
+ Data.Aeson.Encoding.Internal: [fromEncoding] :: Encoding' tag -> Builder
+ Data.Aeson.Encoding.Internal: bool :: Bool -> Encoding
+ Data.Aeson.Encoding.Internal: closeBracket :: Encoding' a
+ Data.Aeson.Encoding.Internal: closeCurly :: Encoding' a
+ Data.Aeson.Encoding.Internal: colon :: Encoding' a
+ Data.Aeson.Encoding.Internal: comma :: Encoding' a
+ Data.Aeson.Encoding.Internal: data InArray
+ Data.Aeson.Encoding.Internal: data Series
+ Data.Aeson.Encoding.Internal: day :: Day -> Encoding' a
+ Data.Aeson.Encoding.Internal: dict :: (k -> Encoding' Text) -> (v -> Encoding) -> (forall a. (k -> v -> a -> a) -> a -> m -> a) -> m -> Encoding
+ Data.Aeson.Encoding.Internal: double :: Double -> Encoding
+ Data.Aeson.Encoding.Internal: doubleText :: Double -> Encoding' a
+ Data.Aeson.Encoding.Internal: econcat :: [Encoding' a] -> Encoding' a
+ Data.Aeson.Encoding.Internal: empty :: Encoding' a
+ Data.Aeson.Encoding.Internal: emptyArray_ :: Encoding
+ Data.Aeson.Encoding.Internal: emptyObject_ :: Encoding
+ Data.Aeson.Encoding.Internal: encodingToLazyByteString :: Encoding' a -> ByteString
+ Data.Aeson.Encoding.Internal: float :: Float -> Encoding
+ Data.Aeson.Encoding.Internal: floatText :: Float -> Encoding' a
+ Data.Aeson.Encoding.Internal: infixr 6 ><
+ Data.Aeson.Encoding.Internal: instance Data.Semigroup.Semigroup Data.Aeson.Encoding.Internal.Series
+ Data.Aeson.Encoding.Internal: instance GHC.Base.Monoid Data.Aeson.Encoding.Internal.Series
+ Data.Aeson.Encoding.Internal: instance GHC.Classes.Eq (Data.Aeson.Encoding.Internal.Encoding' a)
+ Data.Aeson.Encoding.Internal: instance GHC.Classes.Ord (Data.Aeson.Encoding.Internal.Encoding' a)
+ Data.Aeson.Encoding.Internal: instance GHC.Show.Show (Data.Aeson.Encoding.Internal.Encoding' a)
+ Data.Aeson.Encoding.Internal: int :: Int -> Encoding
+ Data.Aeson.Encoding.Internal: int16 :: Int16 -> Encoding
+ Data.Aeson.Encoding.Internal: int16Text :: Int16 -> Encoding' a
+ Data.Aeson.Encoding.Internal: int32 :: Int32 -> Encoding
+ Data.Aeson.Encoding.Internal: int32Text :: Int32 -> Encoding' a
+ Data.Aeson.Encoding.Internal: int64 :: Int64 -> Encoding
+ Data.Aeson.Encoding.Internal: int64Text :: Int64 -> Encoding' a
+ Data.Aeson.Encoding.Internal: int8 :: Int8 -> Encoding
+ Data.Aeson.Encoding.Internal: int8Text :: Int8 -> Encoding' a
+ Data.Aeson.Encoding.Internal: intText :: Int -> Encoding' a
+ Data.Aeson.Encoding.Internal: integer :: Integer -> Encoding
+ Data.Aeson.Encoding.Internal: integerText :: Integer -> Encoding' a
+ Data.Aeson.Encoding.Internal: lazyText :: Text -> Encoding' a
+ Data.Aeson.Encoding.Internal: list :: (a -> Encoding) -> [a] -> Encoding
+ Data.Aeson.Encoding.Internal: localTime :: LocalTime -> Encoding' a
+ Data.Aeson.Encoding.Internal: newtype Encoding' tag
+ Data.Aeson.Encoding.Internal: nullEncoding :: Encoding' a -> Bool
+ Data.Aeson.Encoding.Internal: null_ :: Encoding
+ Data.Aeson.Encoding.Internal: openBracket :: Encoding' a
+ Data.Aeson.Encoding.Internal: openCurly :: Encoding' a
+ Data.Aeson.Encoding.Internal: pair :: Text -> Encoding -> Series
+ Data.Aeson.Encoding.Internal: pairs :: Series -> Encoding
+ Data.Aeson.Encoding.Internal: retagEncoding :: Encoding' a -> Encoding' b
+ Data.Aeson.Encoding.Internal: scientific :: Scientific -> Encoding
+ Data.Aeson.Encoding.Internal: scientificText :: Scientific -> Encoding' a
+ Data.Aeson.Encoding.Internal: string :: String -> Encoding' a
+ Data.Aeson.Encoding.Internal: text :: Text -> Encoding' a
+ Data.Aeson.Encoding.Internal: timeOfDay :: TimeOfDay -> Encoding' a
+ Data.Aeson.Encoding.Internal: tuple :: Encoding' InArray -> Encoding
+ Data.Aeson.Encoding.Internal: type Encoding = Encoding' Value
+ Data.Aeson.Encoding.Internal: unsafeToEncoding :: Builder -> Encoding' a
+ Data.Aeson.Encoding.Internal: utcTime :: UTCTime -> Encoding' a
+ Data.Aeson.Encoding.Internal: value :: Value -> Encoding
+ Data.Aeson.Encoding.Internal: word :: Word -> Encoding
+ Data.Aeson.Encoding.Internal: word16 :: Word16 -> Encoding
+ Data.Aeson.Encoding.Internal: word16Text :: Word16 -> Encoding' a
+ Data.Aeson.Encoding.Internal: word32 :: Word32 -> Encoding
+ Data.Aeson.Encoding.Internal: word32Text :: Word32 -> Encoding' a
+ Data.Aeson.Encoding.Internal: word64 :: Word64 -> Encoding
+ Data.Aeson.Encoding.Internal: word64Text :: Word64 -> Encoding' a
+ Data.Aeson.Encoding.Internal: word8 :: Word8 -> Encoding
+ Data.Aeson.Encoding.Internal: word8Text :: Word8 -> Encoding' a
+ Data.Aeson.Encoding.Internal: wordText :: Word -> Encoding' a
+ Data.Aeson.Encoding.Internal: wrapArray :: Encoding' a -> Encoding
+ Data.Aeson.Encoding.Internal: wrapObject :: Encoding' a -> Encoding
+ Data.Aeson.Encoding.Internal: zonedTime :: ZonedTime -> Encoding' a
+ Data.Aeson.Parser: decodeStrictWith :: Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
+ Data.Aeson.Parser: decodeWith :: Parser Value -> (Value -> Result a) -> ByteString -> Maybe a
+ Data.Aeson.Parser: eitherDecodeStrictWith :: Parser Value -> (Value -> IResult a) -> ByteString -> Either (JSONPath, String) a
+ Data.Aeson.Parser: eitherDecodeWith :: Parser Value -> (Value -> IResult a) -> ByteString -> Either (JSONPath, String) a
+ Data.Aeson.TH: UntaggedValue :: SumEncoding
+ Data.Aeson.TH: deriveFromJSON1 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: deriveFromJSON2 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: deriveJSON1 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: deriveJSON2 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: deriveToJSON1 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: deriveToJSON2 :: Options -> Name -> Q [Dec]
+ Data.Aeson.TH: instance Data.Aeson.TH.LookupField (GHC.Base.Maybe a)
+ Data.Aeson.TH: instance Data.Aeson.TH.LookupField a
+ Data.Aeson.TH: instance GHC.Classes.Eq Data.Aeson.TH.Arity
+ Data.Aeson.TH: instance GHC.Classes.Eq Data.Aeson.TH.StarKindStatus
+ Data.Aeson.TH: instance GHC.Classes.Ord Data.Aeson.TH.Arity
+ Data.Aeson.TH: instance GHC.Enum.Enum Data.Aeson.TH.Arity
+ Data.Aeson.TH: mkLiftParseJSON :: Options -> Name -> Q Exp
+ Data.Aeson.TH: mkLiftParseJSON2 :: Options -> Name -> Q Exp
+ Data.Aeson.TH: mkLiftToEncoding :: Options -> Name -> Q Exp
+ Data.Aeson.TH: mkLiftToEncoding2 :: Options -> Name -> Q Exp
+ Data.Aeson.TH: mkLiftToJSON :: Options -> Name -> Q Exp
+ Data.Aeson.TH: mkLiftToJSON2 :: Options -> Name -> Q Exp
+ Data.Aeson.Text: encodeToLazyText :: ToJSON a => a -> Text
+ Data.Aeson.Text: encodeToTextBuilder :: ToJSON a => a -> Builder
+ Data.Aeson.Types: FromJSONKeyCoerce :: !(CoerceText a) -> FromJSONKeyFunction a
+ Data.Aeson.Types: FromJSONKeyText :: !(Text -> a) -> FromJSONKeyFunction a
+ Data.Aeson.Types: FromJSONKeyTextParser :: !(Text -> Parser a) -> FromJSONKeyFunction a
+ Data.Aeson.Types: FromJSONKeyValue :: !(Value -> Parser a) -> FromJSONKeyFunction a
+ Data.Aeson.Types: ToJSONKeyText :: !(a -> Text) -> !(a -> Encoding' Text) -> ToJSONKeyFunction a
+ Data.Aeson.Types: ToJSONKeyValue :: !(a -> Value) -> !(a -> Encoding) -> ToJSONKeyFunction a
+ Data.Aeson.Types: UntaggedValue :: SumEncoding
+ Data.Aeson.Types: [From1Args] :: (Value -> Parser a) -> (Value -> Parser [a]) -> FromArgs One a
+ Data.Aeson.Types: [NoFromArgs] :: FromArgs Zero a
+ Data.Aeson.Types: [NoToArgs] :: ToArgs res Zero a
+ Data.Aeson.Types: [To1Args] :: (a -> res) -> ([a] -> res) -> ToArgs res One a
+ Data.Aeson.Types: class FromJSON1 f where liftParseJSON = genericLiftParseJSON defaultOptions liftParseJSONList f g v = listParser (liftParseJSON f g) v
+ Data.Aeson.Types: class FromJSON2 f where liftParseJSONList2 fa ga fb gb v = case v of { Array vals -> fmap toList (mapM (liftParseJSON2 fa ga fb gb) vals) _ -> typeMismatch "[a]" v }
+ Data.Aeson.Types: class FromJSONKey a where fromJSONKey = FromJSONKeyValue parseJSON fromJSONKeyList = FromJSONKeyValue parseJSON
+ Data.Aeson.Types: class ToJSON1 f where liftToJSON = genericLiftToJSON defaultOptions liftToJSONList f g = listValue (liftToJSON f g) liftToEncoding = genericLiftToEncoding defaultOptions liftToEncodingList f g = listEncoding (liftToEncoding f g)
+ Data.Aeson.Types: class ToJSON2 f where liftToJSONList2 fa ga fb gb = listValue (liftToJSON2 fa ga fb gb) liftToEncodingList2 fa ga fb gb = listEncoding (liftToEncoding2 fa ga fb gb)
+ Data.Aeson.Types: class ToJSONKey a where toJSONKey = ToJSONKeyValue toJSON toEncoding toJSONKeyList = ToJSONKeyValue toJSON toEncoding
+ Data.Aeson.Types: coerceFromJSONKeyFunction :: Coercible a b => FromJSONKeyFunction a -> FromJSONKeyFunction b
+ Data.Aeson.Types: contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b
+ Data.Aeson.Types: data FromArgs arity a
+ Data.Aeson.Types: data FromJSONKeyFunction a
+ Data.Aeson.Types: data One
+ Data.Aeson.Types: data ToArgs res arity a
+ Data.Aeson.Types: data ToJSONKeyFunction a
+ Data.Aeson.Types: data Zero
+ Data.Aeson.Types: fromJSONKey :: (FromJSONKey a, FromJSON a) => FromJSONKeyFunction a
+ Data.Aeson.Types: fromJSONKeyCoerce :: Coercible Text a => FromJSONKeyFunction a
+ Data.Aeson.Types: fromJSONKeyList :: (FromJSONKey a, FromJSON a) => FromJSONKeyFunction [a]
+ Data.Aeson.Types: genericLiftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f)) => Options -> (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
+ Data.Aeson.Types: genericLiftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f)) => Options -> (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
+ Data.Aeson.Types: genericLiftToJSON :: (Generic1 f, GToJSON One (Rep1 f)) => Options -> (a -> Value) -> ([a] -> Value) -> f a -> Value
+ Data.Aeson.Types: liftParseJSON :: (FromJSON1 f, Generic1 f, GFromJSON One (Rep1 f)) => (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
+ Data.Aeson.Types: liftParseJSON2 :: FromJSON2 f => (Value -> Parser a) -> (Value -> Parser [a]) -> (Value -> Parser b) -> (Value -> Parser [b]) -> Value -> Parser (f a b)
+ Data.Aeson.Types: liftParseJSONList :: FromJSON1 f => (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser [f a]
+ Data.Aeson.Types: liftParseJSONList2 :: FromJSON2 f => (Value -> Parser a) -> (Value -> Parser [a]) -> (Value -> Parser b) -> (Value -> Parser [b]) -> Value -> Parser [f a b]
+ Data.Aeson.Types: liftToEncoding :: (ToJSON1 f, Generic1 f, GToEncoding One (Rep1 f)) => (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
+ Data.Aeson.Types: liftToEncoding2 :: ToJSON2 f => (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> f a b -> Encoding
+ Data.Aeson.Types: liftToEncodingList :: ToJSON1 f => (a -> Encoding) -> ([a] -> Encoding) -> [f a] -> Encoding
+ Data.Aeson.Types: liftToEncodingList2 :: ToJSON2 f => (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> [f a b] -> Encoding
+ Data.Aeson.Types: liftToJSON :: (ToJSON1 f, Generic1 f, GToJSON One (Rep1 f)) => (a -> Value) -> ([a] -> Value) -> f a -> Value
+ Data.Aeson.Types: liftToJSON2 :: ToJSON2 f => (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> f a b -> Value
+ Data.Aeson.Types: liftToJSONList :: ToJSON1 f => (a -> Value) -> ([a] -> Value) -> [f a] -> Value
+ Data.Aeson.Types: liftToJSONList2 :: ToJSON2 f => (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> [f a b] -> Value
+ Data.Aeson.Types: listEncoding :: (a -> Encoding) -> [a] -> Encoding
+ Data.Aeson.Types: listParser :: (Value -> Parser a) -> Value -> Parser [a]
+ Data.Aeson.Types: listValue :: (a -> Value) -> [a] -> Value
+ Data.Aeson.Types: mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
+ Data.Aeson.Types: parseJSON1 :: (FromJSON1 f, FromJSON a) => Value -> Parser (f a)
+ Data.Aeson.Types: parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser (f a b)
+ Data.Aeson.Types: parseJSONList :: FromJSON a => Value -> Parser [a]
+ Data.Aeson.Types: toEncoding1 :: (ToJSON1 f, ToJSON a) => f a -> Encoding
+ Data.Aeson.Types: toEncoding2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Encoding
+ Data.Aeson.Types: toEncodingList :: ToJSON a => [a] -> Encoding
+ Data.Aeson.Types: toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value
+ Data.Aeson.Types: toJSON2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Value
+ Data.Aeson.Types: toJSONKey :: (ToJSONKey a, ToJSON a) => ToJSONKeyFunction a
+ Data.Aeson.Types: toJSONKeyList :: (ToJSONKey a, ToJSON a) => ToJSONKeyFunction [a]
+ Data.Aeson.Types: toJSONKeyText :: (a -> Text) -> ToJSONKeyFunction a
+ Data.Aeson.Types: toJSONList :: ToJSON a => [a] -> Value
+ Data.Aeson.Types: type Encoding = Encoding' Value
- Data.Aeson: class FromJSON a where parseJSON = genericParseJSON defaultOptions
+ Data.Aeson: class FromJSON a where parseJSON = genericParseJSON defaultOptions parseJSONList (Array a) = zipWithM (parseIndexedJSON parseJSON) [0 .. ] . toList $ a parseJSONList v = typeMismatch "[a]" v
- Data.Aeson: class GFromJSON f
+ Data.Aeson: class GFromJSON arity f
- Data.Aeson: class GToEncoding f
+ Data.Aeson: class GToEncoding arity f
- Data.Aeson: class GToJSON f
+ Data.Aeson: class GToJSON arity f
- Data.Aeson: class ToJSON a where toJSON = genericToJSON defaultOptions toEncoding = Encoding . encodeToBuilder . toJSON
+ Data.Aeson: class ToJSON a where toJSON = genericToJSON defaultOptions toEncoding = value . toJSON toJSONList = listValue toJSON toEncodingList = listEncoding toEncoding
- Data.Aeson: encode :: ToJSON a => a -> ByteString
+ Data.Aeson: encode :: (ToJSON a) => a -> ByteString
- Data.Aeson: fromEncoding :: Encoding -> Builder
+ Data.Aeson: fromEncoding :: Encoding' tag -> Builder
- Data.Aeson: gParseJSON :: GFromJSON f => Options -> Value -> Parser (f a)
+ Data.Aeson: gParseJSON :: GFromJSON arity f => Options -> FromArgs arity a -> Value -> Parser (f a)
- Data.Aeson: gToEncoding :: GToEncoding f => Options -> f a -> Encoding
+ Data.Aeson: gToEncoding :: GToEncoding arity f => Options -> ToArgs Encoding arity a -> f a -> Encoding
- Data.Aeson: gToJSON :: GToJSON f => Options -> f a -> Value
+ Data.Aeson: gToJSON :: GToJSON arity f => Options -> ToArgs Value arity a -> f a -> Value
- Data.Aeson: genericParseJSON :: (Generic a, GFromJSON (Rep a)) => Options -> Value -> Parser a
+ Data.Aeson: genericParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Options -> Value -> Parser a
- Data.Aeson: genericToEncoding :: (Generic a, GToEncoding (Rep a)) => Options -> a -> Encoding
+ Data.Aeson: genericToEncoding :: (Generic a, GToEncoding Zero (Rep a)) => Options -> a -> Encoding
- Data.Aeson: genericToJSON :: (Generic a, GToJSON (Rep a)) => Options -> a -> Value
+ Data.Aeson: genericToJSON :: (Generic a, GToJSON Zero (Rep a)) => Options -> a -> Value
- Data.Aeson: parseJSON :: (FromJSON a, Generic a, GFromJSON (Rep a)) => Value -> Parser a
+ Data.Aeson: parseJSON :: (FromJSON a, Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
- Data.Aeson: toJSON :: (ToJSON a, Generic a, GToJSON (Rep a)) => a -> Value
+ Data.Aeson: toJSON :: (ToJSON a, Generic a, GToJSON Zero (Rep a)) => a -> Value
- Data.Aeson.Types: class FromJSON a where parseJSON = genericParseJSON defaultOptions
+ Data.Aeson.Types: class FromJSON a where parseJSON = genericParseJSON defaultOptions parseJSONList (Array a) = zipWithM (parseIndexedJSON parseJSON) [0 .. ] . toList $ a parseJSONList v = typeMismatch "[a]" v
- Data.Aeson.Types: class GFromJSON f
+ Data.Aeson.Types: class GFromJSON arity f
- Data.Aeson.Types: class GToEncoding f
+ Data.Aeson.Types: class GToEncoding arity f
- Data.Aeson.Types: class GToJSON f
+ Data.Aeson.Types: class GToJSON arity f
- Data.Aeson.Types: class ToJSON a where toJSON = genericToJSON defaultOptions toEncoding = Encoding . encodeToBuilder . toJSON
+ Data.Aeson.Types: class ToJSON a where toJSON = genericToJSON defaultOptions toEncoding = value . toJSON toJSONList = listValue toJSON toEncodingList = listEncoding toEncoding
- Data.Aeson.Types: fromEncoding :: Encoding -> Builder
+ Data.Aeson.Types: fromEncoding :: Encoding' tag -> Builder
- Data.Aeson.Types: gParseJSON :: GFromJSON f => Options -> Value -> Parser (f a)
+ Data.Aeson.Types: gParseJSON :: GFromJSON arity f => Options -> FromArgs arity a -> Value -> Parser (f a)
- Data.Aeson.Types: gToEncoding :: GToEncoding f => Options -> f a -> Encoding
+ Data.Aeson.Types: gToEncoding :: GToEncoding arity f => Options -> ToArgs Encoding arity a -> f a -> Encoding
- Data.Aeson.Types: gToJSON :: GToJSON f => Options -> f a -> Value
+ Data.Aeson.Types: gToJSON :: GToJSON arity f => Options -> ToArgs Value arity a -> f a -> Value
- Data.Aeson.Types: genericParseJSON :: (Generic a, GFromJSON (Rep a)) => Options -> Value -> Parser a
+ Data.Aeson.Types: genericParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Options -> Value -> Parser a
- Data.Aeson.Types: genericToEncoding :: (Generic a, GToEncoding (Rep a)) => Options -> a -> Encoding
+ Data.Aeson.Types: genericToEncoding :: (Generic a, GToEncoding Zero (Rep a)) => Options -> a -> Encoding
- Data.Aeson.Types: genericToJSON :: (Generic a, GToJSON (Rep a)) => Options -> a -> Value
+ Data.Aeson.Types: genericToJSON :: (Generic a, GToJSON Zero (Rep a)) => Options -> a -> Value
- Data.Aeson.Types: parseJSON :: (FromJSON a, Generic a, GFromJSON (Rep a)) => Value -> Parser a
+ Data.Aeson.Types: parseJSON :: (FromJSON a, Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
- Data.Aeson.Types: toJSON :: (ToJSON a, Generic a, GToJSON (Rep a)) => a -> Value
+ Data.Aeson.Types: toJSON :: (ToJSON a, Generic a, GToJSON Zero (Rep a)) => a -> Value
- Data.Aeson.Types: unsafeToEncoding :: Builder -> Encoding
+ Data.Aeson.Types: unsafeToEncoding :: Builder -> Encoding' a

Files

Data/Aeson.hs view
@@ -57,13 +57,36 @@     , fromJSON     , ToJSON(..)     , KeyValue(..)+    -- ** Keys for maps+    , ToJSONKey(..)+    , ToJSONKeyFunction(..)+    , FromJSONKey(..)+    , FromJSONKeyFunction(..)+    -- ** Liftings to unary and binary type constructors+    , FromJSON1(..)+    , parseJSON1+    , FromJSON2(..)+    , parseJSON2+    , ToJSON1(..)+    , toJSON1+    , toEncoding1+    , ToJSON2(..)+    , toJSON2+    , toEncoding2     -- ** Generic JSON classes and options     , GFromJSON(..)+    , FromArgs(..)     , GToJSON(..)     , GToEncoding(..)+    , ToArgs(..)+    , Zero+    , One     , genericToJSON+    , genericLiftToJSON     , genericToEncoding+    , genericLiftToEncoding     , genericParseJSON+    , genericLiftParseJSON     , defaultOptions      -- * Inspecting @'Value's@@@ -87,16 +110,23 @@     , json'     ) where -import Data.Aeson.Encode (encode)-import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith,-                                   eitherDecodeWith, eitherDecodeStrictWith,-                                   jsonEOF, json, jsonEOF', json')+import Prelude ()+import Prelude.Compat++import Data.Aeson.Types.FromJSON (ifromJSON)+import Data.Aeson.Encoding (encodingToLazyByteString)+import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith, eitherDecodeWith, eitherDecodeStrictWith, jsonEOF, json, jsonEOF', json') import Data.Aeson.Types-import Data.Aeson.Types.Instances (ifromJSON) import Data.Aeson.Types.Internal (JSONPath, formatError) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L +-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.+--+-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.+encode :: (ToJSON a) => a -> L.ByteString+encode = encodingToLazyByteString . toEncoding+ -- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'. -- If this fails due to incomplete or invalid input, 'Nothing' is -- returned.@@ -136,7 +166,7 @@ decode' = decodeWith jsonEOF' fromJSON {-# INLINE decode' #-} --- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.+-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'. -- If this fails due to incomplete or invalid input, 'Nothing' is -- returned. --
Data/Aeson/Encode.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}- -- | -- Module:      Data.Aeson.Encode -- Copyright:   (c) 2012-2016 Bryan O'Sullivan@@ -9,92 +7,24 @@ -- Stability:   experimental -- Portability: portable ----- Efficiently serialize a JSON value.------ Most frequently, you'll probably want to encode straight to UTF-8--- (the standard JSON encoding) using 'encode'.------ You can use the conversions to 'Builder's when embedding JSON messages as--- parts of a protocol.-module Data.Aeson.Encode-    ( encode--    -- * Encoding to Builders-    , encodeToBuilder+-- This module is left to supply limited backwards-compatibility.+module Data.Aeson.Encode {-# DEPRECATED "Use Data.Aeson or Data.Aeson.Text instead" #-}+    (+      encode     , encodeToTextBuilder--    -- * Deprecated-    , fromValue     ) where -import Data.Aeson.Encode.Builder (encodeToBuilder)-import Data.Aeson.Encode.Functions (encode)-import Data.Aeson.Types (Value(..))-import Data.Monoid ((<>))-import Data.Scientific (FPFormat(..), Scientific, base10Exponent)-import Data.Text.Lazy.Builder-import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)-import Numeric (showHex)-import qualified Data.HashMap.Strict as H-import qualified Data.Text as T-import qualified Data.Vector as V---- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be--- embedded efficiently in a text-based protocol.------ If you are going to immediately encode straight to a--- 'L.ByteString', it is more efficient to use 'encodeToBuilder'--- instead.-encodeToTextBuilder :: Value -> Builder-encodeToTextBuilder =-    go-  where-    go Null       = {-# SCC "go/Null" #-} "null"-    go (Bool b)   = {-# SCC "go/Bool" #-} if b then "true" else "false"-    go (Number s) = {-# SCC "go/Number" #-} fromScientific s-    go (String s) = {-# SCC "go/String" #-} string s-    go (Array v)-        | V.null v = {-# SCC "go/Array" #-} "[]"-        | otherwise = {-# SCC "go/Array" #-}-                      singleton '[' <>-                      go (V.unsafeHead v) <>-                      V.foldr f (singleton ']') (V.unsafeTail v)-      where f a z = singleton ',' <> go a <> z-    go (Object m) = {-# SCC "go/Object" #-}-        case H.toList m of-          (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs-          _      -> "{}"-      where f a z     = singleton ',' <> one a <> z-            one (k,v) = string k <> singleton ':' <> go v--{-# DEPRECATED fromValue "Use 'encodeToTextBuilder' instead" #-}-fromValue :: Value -> Builder-fromValue = encodeToTextBuilder+import Prelude () -string :: T.Text -> Builder-string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'-  where-    quote q = case T.uncons t of-                Nothing      -> fromText h-                Just (!c,t') -> fromText h <> escape c <> quote t'-        where (h,t) = {-# SCC "break" #-} T.break isEscape q-    isEscape c = c == '\"' ||-                 c == '\\' ||-                 c < '\x20'-    escape '\"' = "\\\""-    escape '\\' = "\\\\"-    escape '\n' = "\\n"-    escape '\r' = "\\r"-    escape '\t' = "\\t"+import Data.ByteString.Lazy (ByteString)+import Data.Text.Lazy.Builder (Builder)+import qualified Data.Aeson as A+import qualified Data.Aeson.Text as A -    escape c-        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h-        | otherwise  = singleton c-        where h = showHex (fromEnum c) ""+encode :: A.ToJSON a => a -> ByteString+encode = A.encode+{-# DEPRECATED encode "Use encode from Data.Aeson" #-} -fromScientific :: Scientific -> Builder-fromScientific s = formatScientificBuilder format prec s-  where-    (format, prec)-      | base10Exponent s < 0 = (Generic, Nothing)-      | otherwise            = (Fixed,   Just 0)+encodeToTextBuilder :: A.Value -> Builder+encodeToTextBuilder = A.encodeToTextBuilder+{-# DEPRECATED encodeToTextBuilder "Use encodeTotextBuilder from Data.Aeson.Text" #-}
− Data/Aeson/Encode/Builder.hs
@@ -1,260 +0,0 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}---- |--- Module:      Data.Aeson.Encode.Builder--- Copyright:   (c) 2011 MailRank, Inc.---              (c) 2013 Simon Meier <iridcode@gmail.com>--- License:     BSD3--- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>--- Stability:   experimental--- Portability: portable------ Efficiently serialize a JSON value using the UTF-8 encoding.--module Data.Aeson.Encode.Builder-    (-      encodeToBuilder-    , null_-    , bool-    , array-    , emptyArray_-    , emptyObject_-    , object-    , text-    , string-    , unquoted-    , quote-    , number-    , day-    , localTime-    , utcTime-    , timeOfDay-    , zonedTime-    , ascii2-    , ascii4-    , ascii5-    ) where--import Data.Aeson.Internal.Time-import Data.Aeson.Types.Internal (Encoding(..), Value(..))-import Data.ByteString.Builder as B-import Data.ByteString.Builder.Prim as BP-import Data.ByteString.Builder.Scientific (scientificBuilder)-import Data.Char (chr, ord)-import Data.Monoid ((<>))-import Data.Scientific (Scientific, base10Exponent, coefficient)-import Data.Time (UTCTime(..))-import Data.Time.Calendar (Day(..), toGregorian)-import Data.Time.LocalTime-import Data.Word (Word8)-import qualified Data.HashMap.Strict as HMS-import qualified Data.Text as T-import qualified Data.Text.Encoding as TE-import qualified Data.Vector as V---- | Encode a JSON value to a "Data.ByteString" 'B.Builder'.------ Use this function if you are encoding over the wire, or need to--- prepend or append further bytes to the encoded JSON value.-encodeToBuilder :: Value -> Builder-encodeToBuilder Null       = null_-encodeToBuilder (Bool b)   = bool b-encodeToBuilder (Number n) = number n-encodeToBuilder (String s) = text s-encodeToBuilder (Array v)  = array v-encodeToBuilder (Object m) = object m---- | Encode a JSON null.-null_ :: Builder-null_ = BP.primBounded (ascii4 ('n',('u',('l','l')))) ()---- | Encode a JSON boolean.-bool :: Bool -> Builder-bool = BP.primBounded (BP.condB id (ascii4 ('t',('r',('u','e'))))-                                   (ascii5 ('f',('a',('l',('s','e'))))))---- | Encode a JSON array.-array :: V.Vector Value -> Builder-array v-  | V.null v  = emptyArray__-  | otherwise = B.char8 '[' <>-                encodeToBuilder (V.unsafeHead v) <>-                V.foldr withComma (B.char8 ']') (V.unsafeTail v)-  where-    withComma a z = B.char8 ',' <> encodeToBuilder a <> z---- Encode a JSON object.-object :: HMS.HashMap T.Text Value -> Builder-object m = case HMS.toList m of-    (x:xs) -> B.char8 '{' <> one x <> foldr withComma (B.char8 '}') xs-    _      -> emptyObject__-  where-    withComma a z = B.char8 ',' <> one a <> z-    one (k,v)     = text k <> B.char8 ':' <> encodeToBuilder v---- | Encode a JSON string.-text :: T.Text -> Builder-text t = B.char8 '"' <> unquoted t <> B.char8 '"'---- | Encode a JSON string, without enclosing quotes.-unquoted :: T.Text -> Builder-unquoted t = TE.encodeUtf8BuilderEscaped escapeAscii t---- | Add quotes surrounding a builder-quote :: Builder -> Builder-quote b = B.char8 '"' <> b <> B.char8 '"'---- | Encode a JSON string.-string :: String -> Builder-string t = B.char8 '"' <> BP.primMapListBounded go t <> B.char8 '"'-  where go = BP.condB (> '\x7f') BP.charUtf8 (c2w >$< escapeAscii)--escapeAscii :: BP.BoundedPrim Word8-escapeAscii =-    BP.condB (== c2w '\\'  ) (ascii2 ('\\','\\')) $-    BP.condB (== c2w '\"'  ) (ascii2 ('\\','"' )) $-    BP.condB (>= c2w '\x20') (BP.liftFixedToBounded BP.word8) $-    BP.condB (== c2w '\n'  ) (ascii2 ('\\','n' )) $-    BP.condB (== c2w '\r'  ) (ascii2 ('\\','r' )) $-    BP.condB (== c2w '\t'  ) (ascii2 ('\\','t' )) $-    (BP.liftFixedToBounded hexEscape) -- fallback for chars < 0x20-  where-    hexEscape :: BP.FixedPrim Word8-    hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<-        BP.char8 >*< BP.char8 >*< BP.word16HexFixed-{-# INLINE escapeAscii #-}--c2w :: Char -> Word8-c2w c = fromIntegral (ord c)---- | Encode a JSON number.-number :: Scientific -> Builder-number s-    | e < 0     = scientificBuilder s-    | otherwise = B.integerDec (coefficient s * 10 ^ e)-  where-    e = base10Exponent s--emptyArray_ :: Encoding-emptyArray_ = Encoding emptyArray__--emptyArray__ :: Builder-emptyArray__ = BP.primBounded (ascii2 ('[',']')) ()--emptyObject_ :: Encoding-emptyObject_ = Encoding emptyObject__--emptyObject__ :: Builder-emptyObject__ = BP.primBounded (ascii2 ('{','}')) ()--ascii2 :: (Char, Char) -> BP.BoundedPrim a-ascii2 cs = BP.liftFixedToBounded $ (const cs) BP.>$< BP.char7 >*< BP.char7-{-# INLINE ascii2 #-}--ascii4 :: (Char, (Char, (Char, Char))) -> BP.BoundedPrim a-ascii4 cs = BP.liftFixedToBounded $ (const cs) >$<-    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7-{-# INLINE ascii4 #-}--ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BP.BoundedPrim a-ascii5 cs = BP.liftFixedToBounded $ (const cs) >$<-    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7-{-# INLINE ascii5 #-}--ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BP.BoundedPrim a-ascii6 cs = BP.liftFixedToBounded $ (const cs) >$<-    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7-{-# INLINE ascii6 #-}--ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char)))))))-       -> BP.BoundedPrim a-ascii8 cs = BP.liftFixedToBounded $ (const cs) >$<-    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*<-    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7-{-# INLINE ascii8 #-}--day :: Day -> Builder-day dd = encodeYear yr <>-         BP.primBounded (ascii6 ('-',(mh,(ml,('-',(dh,dl)))))) ()-  where (yr,m,d)    = toGregorian dd-        !(T mh ml)  = twoDigits m-        !(T dh dl)  = twoDigits d-        encodeYear y-            | y >= 1000 = B.integerDec y-            | y >= 0    = BP.primBounded (ascii4 (padYear y)) ()-            | y >= -999 = BP.primBounded (ascii5 ('-',padYear (- y))) ()-            | otherwise = B.integerDec y-        padYear y =-            let (ab,c) = fromIntegral y `quotRem` 10-                (a,b)  = ab `quotRem` 10-            in ('0',(digit a,(digit b,digit c)))-{-# INLINE day #-}--timeOfDay :: TimeOfDay -> Builder-timeOfDay t = timeOfDay64 (toTimeOfDay64 t)-{-# INLINE timeOfDay #-}--timeOfDay64 :: TimeOfDay64 -> Builder-timeOfDay64 (TOD h m s)-  | frac == 0 = hhmmss -- omit subseconds if 0-  | otherwise = hhmmss <> BP.primBounded showFrac frac-  where-    hhmmss  = BP.primBounded (ascii8 (hh,(hl,(':',(mh,(ml,(':',(sh,sl)))))))) ()-    !(T hh hl)  = twoDigits h-    !(T mh ml)  = twoDigits m-    !(T sh sl)  = twoDigits (fromIntegral real)-    (real,frac) = s `quotRem` pico-    showFrac = (\x -> ('.', x)) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)-    trunc12 = (`quotRem` micro) >$<-              BP.condB (\(_,y) -> y == 0) (fst >$< trunc6) (digits6 >*< trunc6)-    digits6 = ((`quotRem` milli) . fromIntegral) >$< (digits3 >*< digits3)-    trunc6  = ((`quotRem` milli) . fromIntegral) >$<-              BP.condB (\(_,y) -> y == 0) (fst >$< trunc3) (digits3 >*< trunc3)-    digits3 = (`quotRem` 10) >$< (digits2 >*< digits1)-    digits2 = (`quotRem` 10) >$< (digits1 >*< digits1)-    digits1 = BP.liftFixedToBounded (digit >$< BP.char7)-    trunc3  = BP.condB (== 0) BP.emptyB $-              (`quotRem` 100) >$< (digits1 >*< trunc2)-    trunc2  = BP.condB (== 0) BP.emptyB $-              (`quotRem` 10)  >$< (digits1 >*< trunc1)-    trunc1  = BP.condB (== 0) BP.emptyB digits1--    pico       = 1000000000000 -- number of picoseconds  in 1 second-    micro      =       1000000 -- number of microseconds in 1 second-    milli      =          1000 -- number of milliseconds in 1 second-{-# INLINE timeOfDay64 #-}--timeZone :: TimeZone -> Builder-timeZone (TimeZone off _ _)-  | off == 0  = B.char7 'Z'-  | otherwise = BP.primBounded (ascii6 (s,(hh,(hl,(':',(mh,ml)))))) ()-  where !s         = if off < 0 then '-' else '+'-        !(T hh hl) = twoDigits h-        !(T mh ml) = twoDigits m-        (h,m)      = abs off `quotRem` 60-{-# INLINE timeZone #-}--dayTime :: Day -> TimeOfDay64 -> Builder-dayTime d t = day d <> B.char7 'T' <> timeOfDay64 t-{-# INLINE dayTime #-}--utcTime :: UTCTime -> B.Builder-utcTime (UTCTime d s) = dayTime d (diffTimeOfDay64 s) <> B.char7 'Z'-{-# INLINE utcTime #-}--localTime :: LocalTime -> Builder-localTime (LocalTime d t) = dayTime d (toTimeOfDay64 t)-{-# INLINE localTime #-}--zonedTime :: ZonedTime -> Builder-zonedTime (ZonedTime t z) = localTime t <> timeZone z-{-# INLINE zonedTime #-}--data T = T {-# UNPACK #-} !Char {-# UNPACK #-} !Char--twoDigits :: Int -> T-twoDigits a     = T (digit hi) (digit lo)-  where (hi,lo) = a `quotRem` 10--digit :: Int -> Char-digit x = chr (x + 48)
− Data/Aeson/Encode/Functions.hs
@@ -1,59 +0,0 @@-{-# LANGUAGE CPP #-}--module Data.Aeson.Encode.Functions-    (-      brackets-    , builder-    , char7-    , encode-    , foldable-    , list-    , pairs-    ) where--import Data.Aeson.Encode.Builder-import Data.Aeson.Types.Class-import Data.Aeson.Types.Internal-import Data.ByteString.Builder (Builder, char7)-import Data.ByteString.Builder.Prim (primBounded)-import Data.Monoid ((<>))-import qualified Data.ByteString.Builder as B-import qualified Data.ByteString.Lazy as L--#if !MIN_VERSION_base(4,8,0)-import Data.Foldable (Foldable, foldMap)-import Data.Monoid (mempty)-#endif--builder :: ToJSON a => a -> Builder-builder = fromEncoding . toEncoding-{-# INLINE builder #-}---- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.------ This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.-encode :: ToJSON a => a -> L.ByteString-encode = B.toLazyByteString . builder-{-# INLINE encode #-}---- | Encode a 'Foldable' as a JSON array.-foldable :: (Foldable t, ToJSON a) => t a -> Encoding-foldable = brackets '[' ']' . foldMap (Value . toEncoding)-{-# INLINE foldable #-}--list :: (ToJSON a) => [a] -> Encoding-list []     = emptyArray_-list (x:xs) = Encoding $-              char7 '[' <> builder x <> commas xs <> char7 ']'-      where commas = foldr (\v vs -> char7 ',' <> builder v <> vs) mempty-{-# INLINE list #-}--brackets :: Char -> Char -> Series -> Encoding-brackets begin end (Value v) = Encoding $-                               char7 begin <> fromEncoding v <> char7 end-brackets begin end Empty     = Encoding (primBounded (ascii2 (begin,end)) ())---- | Encode a series of key/value pairs, separated by commas.-pairs :: Series -> Encoding-pairs s = brackets '{' '}' s-{-# INLINE pairs #-}
+ Data/Aeson/Encoding.hs view
@@ -0,0 +1,52 @@+-- |+--+-- Functions in this module return well-formed 'Encoding''.+-- Polymorphic variants, which return @'Encoding' a@, return a textual JSON+-- value, so it can be used as both @'Encoding'' 'Text'@ and @'Encoding' = 'Encoding'' 'Value'@.+module Data.Aeson.Encoding+    (+    -- * Encoding+      Encoding+    , Encoding'+    , encodingToLazyByteString+    , fromEncoding+    , unsafeToEncoding+    , Series+    , pairs+    , pair+    -- * Predicates+    , nullEncoding+    -- * Encoding constructors+    , emptyArray_+    , emptyObject_+    , text+    , lazyText+    , string+    , list+    , dict+    , null_+    , bool+    -- ** Decimal numbers+    , int8, int16, int32, int64, int+    , word8, word16, word32, word64, word+    , integer, float, double, scientific++    -- ** Decimal numbers as Text+    , int8Text, int16Text, int32Text, int64Text, intText+    , word8Text, word16Text, word32Text, word64Text, wordText+    , integerText, floatText, doubleText, scientificText++    -- ** Time+    , day+    , localTime+    , utcTime+    , timeOfDay+    , zonedTime++    -- ** value+    , value+    ) where++import Prelude ()++import Data.Aeson.Encoding.Internal
+ Data/Aeson/Encoding/Builder.hs view
@@ -0,0 +1,330 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module:      Data.Aeson.Encoding.Builder+-- Copyright:   (c) 2011 MailRank, Inc.+--              (c) 2013 Simon Meier <iridcode@gmail.com>+-- License:     BSD3+-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>+-- Stability:   experimental+-- Portability: portable+--+-- Efficiently serialize a JSON value using the UTF-8 encoding.++module Data.Aeson.Encoding.Builder+    (+      encodeToBuilder+    , null_+    , bool+    , array+    , emptyArray_+    , emptyObject_+    , object+    , text+    , string+    , unquoted+    , quote+    , scientific+    , day+    , localTime+    , utcTime+    , timeOfDay+    , zonedTime+    , ascii2+    , ascii4+    , ascii5+    ) where++import Prelude ()+import Prelude.Compat++import Data.Aeson.Internal.Time+import Data.Aeson.Types.Internal (Value (..))+import Data.ByteString.Builder as B+import Data.ByteString.Builder.Prim as BP+import Data.ByteString.Builder.Scientific (scientificBuilder)+import Data.Char (chr, ord)+import Data.Monoid ((<>))+import Data.Scientific (Scientific, base10Exponent, coefficient)+import Data.Time (UTCTime(..))+import Data.Time.Calendar (Day(..), toGregorian)+import Data.Time.LocalTime+import Data.Word (Word8)+import qualified Data.HashMap.Strict as HMS+import qualified Data.Text as T+import qualified Data.Vector as V++#if MIN_VERSION_bytestring(0,10,4)+import Data.Text.Encoding (encodeUtf8BuilderEscaped)+#else+import Data.Bits ((.&.))+import Data.Text.Internal (Text(..))+import Data.Text.Internal.Unsafe.Shift (shiftR)+import Foreign.Ptr (minusPtr, plusPtr)+import Foreign.Storable (poke)+import qualified Data.ByteString.Builder.Internal as B+import qualified Data.ByteString.Builder.Prim.Internal as BP+import qualified Data.Text.Array as A+import qualified Data.Text.Internal.Encoding.Utf16 as U16+#endif++-- | Encode a JSON value to a "Data.ByteString" 'B.Builder'.+--+-- Use this function if you are encoding over the wire, or need to+-- prepend or append further bytes to the encoded JSON value.+encodeToBuilder :: Value -> Builder+encodeToBuilder Null       = null_+encodeToBuilder (Bool b)   = bool b+encodeToBuilder (Number n) = scientific n+encodeToBuilder (String s) = text s+encodeToBuilder (Array v)  = array v+encodeToBuilder (Object m) = object m++-- | Encode a JSON null.+null_ :: Builder+null_ = BP.primBounded (ascii4 ('n',('u',('l','l')))) ()++-- | Encode a JSON boolean.+bool :: Bool -> Builder+bool = BP.primBounded (BP.condB id (ascii4 ('t',('r',('u','e'))))+                                   (ascii5 ('f',('a',('l',('s','e'))))))++-- | Encode a JSON array.+array :: V.Vector Value -> Builder+array v+  | V.null v  = emptyArray_+  | otherwise = B.char8 '[' <>+                encodeToBuilder (V.unsafeHead v) <>+                V.foldr withComma (B.char8 ']') (V.unsafeTail v)+  where+    withComma a z = B.char8 ',' <> encodeToBuilder a <> z++-- Encode a JSON object.+object :: HMS.HashMap T.Text Value -> Builder+object m = case HMS.toList m of+    (x:xs) -> B.char8 '{' <> one x <> foldr withComma (B.char8 '}') xs+    _      -> emptyObject_+  where+    withComma a z = B.char8 ',' <> one a <> z+    one (k,v)     = text k <> B.char8 ':' <> encodeToBuilder v++-- | Encode a JSON string.+text :: T.Text -> Builder+text t = B.char8 '"' <> unquoted t <> B.char8 '"'++-- | Encode a JSON string, without enclosing quotes.+unquoted :: T.Text -> Builder+unquoted = encodeUtf8BuilderEscaped escapeAscii++-- | Add quotes surrounding a builder+quote :: Builder -> Builder+quote b = B.char8 '"' <> b <> B.char8 '"'++-- | Encode a JSON string.+string :: String -> Builder+string t = B.char8 '"' <> BP.primMapListBounded go t <> B.char8 '"'+  where go = BP.condB (> '\x7f') BP.charUtf8 (c2w >$< escapeAscii)++escapeAscii :: BP.BoundedPrim Word8+escapeAscii =+    BP.condB (== c2w '\\'  ) (ascii2 ('\\','\\')) $+    BP.condB (== c2w '\"'  ) (ascii2 ('\\','"' )) $+    BP.condB (>= c2w '\x20') (BP.liftFixedToBounded BP.word8) $+    BP.condB (== c2w '\n'  ) (ascii2 ('\\','n' )) $+    BP.condB (== c2w '\r'  ) (ascii2 ('\\','r' )) $+    BP.condB (== c2w '\t'  ) (ascii2 ('\\','t' )) $+    BP.liftFixedToBounded hexEscape -- fallback for chars < 0x20+  where+    hexEscape :: BP.FixedPrim Word8+    hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<+        BP.char8 >*< BP.char8 >*< BP.word16HexFixed+{-# INLINE escapeAscii #-}++c2w :: Char -> Word8+c2w c = fromIntegral (ord c)++-- | Encode a JSON number.+scientific :: Scientific -> Builder+scientific s+    | e < 0     = scientificBuilder s+    | otherwise = B.integerDec (coefficient s * 10 ^ e)+  where+    e = base10Exponent s++emptyArray_ :: Builder+emptyArray_ = BP.primBounded (ascii2 ('[',']')) ()++emptyObject_ :: Builder+emptyObject_ = BP.primBounded (ascii2 ('{','}')) ()++ascii2 :: (Char, Char) -> BP.BoundedPrim a+ascii2 cs = BP.liftFixedToBounded $ const cs BP.>$< BP.char7 >*< BP.char7+{-# INLINE ascii2 #-}++ascii4 :: (Char, (Char, (Char, Char))) -> BP.BoundedPrim a+ascii4 cs = BP.liftFixedToBounded $ const cs >$<+    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7+{-# INLINE ascii4 #-}++ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BP.BoundedPrim a+ascii5 cs = BP.liftFixedToBounded $ const cs >$<+    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7+{-# INLINE ascii5 #-}++ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BP.BoundedPrim a+ascii6 cs = BP.liftFixedToBounded $ const cs >$<+    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7+{-# INLINE ascii6 #-}++ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char)))))))+       -> BP.BoundedPrim a+ascii8 cs = BP.liftFixedToBounded $ const cs >$<+    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*<+    BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7+{-# INLINE ascii8 #-}++day :: Day -> Builder+day dd = encodeYear yr <>+         BP.primBounded (ascii6 ('-',(mh,(ml,('-',(dh,dl)))))) ()+  where (yr,m,d)    = toGregorian dd+        !(T mh ml)  = twoDigits m+        !(T dh dl)  = twoDigits d+        encodeYear y+            | y >= 1000 = B.integerDec y+            | y > 0 =+                let (ab,c) = fromIntegral y `quotRem` 10+                    (a,b)  = ab `quotRem` 10+                in BP.primBounded (ascii4 ('0',(digit a,(digit b,digit c)))) ()+            | otherwise =+                error "Data.Aeson.Encode.Builder.day:  years BCE not supported"+{-# INLINE day #-}++timeOfDay :: TimeOfDay -> Builder+timeOfDay t = timeOfDay64 (toTimeOfDay64 t)+{-# INLINE timeOfDay #-}++timeOfDay64 :: TimeOfDay64 -> Builder+timeOfDay64 (TOD h m s)+  | frac == 0 = hhmmss -- omit subseconds if 0+  | otherwise = hhmmss <> BP.primBounded showFrac frac+  where+    hhmmss  = BP.primBounded (ascii8 (hh,(hl,(':',(mh,(ml,(':',(sh,sl)))))))) ()+    !(T hh hl)  = twoDigits h+    !(T mh ml)  = twoDigits m+    !(T sh sl)  = twoDigits (fromIntegral real)+    (real,frac) = s `quotRem` pico+    showFrac = (\x -> ('.', x)) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)+    trunc12 = (`quotRem` micro) >$<+              BP.condB (\(_,y) -> y == 0) (fst >$< trunc6) (digits6 >*< trunc6)+    digits6 = ((`quotRem` milli) . fromIntegral) >$< (digits3 >*< digits3)+    trunc6  = ((`quotRem` milli) . fromIntegral) >$<+              BP.condB (\(_,y) -> y == 0) (fst >$< trunc3) (digits3 >*< trunc3)+    digits3 = (`quotRem` 10) >$< (digits2 >*< digits1)+    digits2 = (`quotRem` 10) >$< (digits1 >*< digits1)+    digits1 = BP.liftFixedToBounded (digit >$< BP.char7)+    trunc3  = BP.condB (== 0) BP.emptyB $+              (`quotRem` 100) >$< (digits1 >*< trunc2)+    trunc2  = BP.condB (== 0) BP.emptyB $+              (`quotRem` 10)  >$< (digits1 >*< trunc1)+    trunc1  = BP.condB (== 0) BP.emptyB digits1++    pico       = 1000000000000 -- number of picoseconds  in 1 second+    micro      =       1000000 -- number of microseconds in 1 second+    milli      =          1000 -- number of milliseconds in 1 second+{-# INLINE timeOfDay64 #-}++timeZone :: TimeZone -> Builder+timeZone (TimeZone off _ _)+  | off == 0  = B.char7 'Z'+  | otherwise = BP.primBounded (ascii6 (s,(hh,(hl,(':',(mh,ml)))))) ()+  where !s         = if off < 0 then '-' else '+'+        !(T hh hl) = twoDigits h+        !(T mh ml) = twoDigits m+        (h,m)      = abs off `quotRem` 60+{-# INLINE timeZone #-}++dayTime :: Day -> TimeOfDay64 -> Builder+dayTime d t = day d <> B.char7 'T' <> timeOfDay64 t+{-# INLINE dayTime #-}++utcTime :: UTCTime -> B.Builder+utcTime (UTCTime d s) = dayTime d (diffTimeOfDay64 s) <> B.char7 'Z'+{-# INLINE utcTime #-}++localTime :: LocalTime -> Builder+localTime (LocalTime d t) = dayTime d (toTimeOfDay64 t)+{-# INLINE localTime #-}++zonedTime :: ZonedTime -> Builder+zonedTime (ZonedTime t z) = localTime t <> timeZone z+{-# INLINE zonedTime #-}++data T = T {-# UNPACK #-} !Char {-# UNPACK #-} !Char++twoDigits :: Int -> T+twoDigits a     = T (digit hi) (digit lo)+  where (hi,lo) = a `quotRem` 10++digit :: Int -> Char+digit x = chr (x + 48)++#if !(MIN_VERSION_bytestring(0,10,4))+-- | Encode text using UTF-8 encoding and escape the ASCII characters using+-- a 'BP.BoundedPrim'.+--+-- Use this function is to implement efficient encoders for text-based formats+-- like JSON or HTML.+{-# INLINE encodeUtf8BuilderEscaped #-}+-- TODO: Extend documentation with references to source code in @blaze-html@+-- or @aeson@ that uses this function.+encodeUtf8BuilderEscaped :: BP.BoundedPrim Word8 -> Text -> B.Builder+encodeUtf8BuilderEscaped be =+    -- manual eta-expansion to ensure inlining works as expected+    \txt -> B.builder (mkBuildstep txt)+  where+    bound = max 4 $ BP.sizeBound be++    mkBuildstep (Text arr off len) !k =+        outerLoop off+      where+        iend = off + len++        outerLoop !i0 !br@(B.BufferRange op0 ope)+          | i0 >= iend       = k br+          | outRemaining > 0 = goPartial (i0 + min outRemaining inpRemaining)+          -- TODO: Use a loop with an integrated bound's check if outRemaining+          -- is smaller than 8, as this will save on divisions.+          | otherwise        = return $ B.bufferFull bound op0 (outerLoop i0)+          where+            outRemaining = (ope `minusPtr` op0) `div` bound+            inpRemaining = iend - i0++            goPartial !iendTmp = go i0 op0+              where+                go !i !op+                  | i < iendTmp = case A.unsafeIndex arr i of+                      w | w <= 0x7F -> do+                            BP.runB be (fromIntegral w) op >>= go (i + 1)+                        | w <= 0x7FF -> do+                            poke8 0 $ (w `shiftR` 6) + 0xC0+                            poke8 1 $ (w .&. 0x3f) + 0x80+                            go (i + 1) (op `plusPtr` 2)+                        | 0xD800 <= w && w <= 0xDBFF -> do+                            let c = ord $ U16.chr2 w (A.unsafeIndex arr (i+1))+                            poke8 0 $ (c `shiftR` 18) + 0xF0+                            poke8 1 $ ((c `shiftR` 12) .&. 0x3F) + 0x80+                            poke8 2 $ ((c `shiftR` 6) .&. 0x3F) + 0x80+                            poke8 3 $ (c .&. 0x3F) + 0x80+                            go (i + 2) (op `plusPtr` 4)+                        | otherwise -> do+                            poke8 0 $ (w `shiftR` 12) + 0xE0+                            poke8 1 $ ((w `shiftR` 6) .&. 0x3F) + 0x80+                            poke8 2 $ (w .&. 0x3F) + 0x80+                            go (i + 1) (op `plusPtr` 3)+                  | otherwise =+                      outerLoop i (B.BufferRange op ope)+                  where+                    poke8 j v = poke (op `plusPtr` j) (fromIntegral v :: Word8)+#endif
+ Data/Aeson/Encoding/Internal.hs view
@@ -0,0 +1,360 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+module Data.Aeson.Encoding.Internal+    (+    -- * Encoding+      Encoding' (..)+    , Encoding+    , encodingToLazyByteString+    , unsafeToEncoding+    , retagEncoding+    , Series (..)+    , pairs+    , pair+    -- * Predicates+    , nullEncoding+    -- * Encoding constructors+    , emptyArray_+    , emptyObject_+    , wrapObject+    , wrapArray+    , null_+    , bool+    , text+    , lazyText+    , string+    , list+    , dict+    , tuple+    , (>*<)+    , InArray+    , empty+    , (><)+    , econcat+    -- ** Decimal numbers+    , int8, int16, int32, int64, int+    , word8, word16, word32, word64, word+    , integer, float, double, scientific+    -- ** Decimal numbers as Text+    , int8Text, int16Text, int32Text, int64Text, intText+    , word8Text, word16Text, word32Text, word64Text, wordText+    , integerText, floatText, doubleText, scientificText+    -- ** Time+    , day+    , localTime+    , utcTime+    , timeOfDay+    , zonedTime+    -- ** value+    , value+    -- ** JSON tokens+    , comma, colon, openBracket, closeBracket, openCurly, closeCurly+    ) where++import Prelude ()+import Prelude.Compat++import Data.Aeson.Types.Internal (Value)+import Data.ByteString.Builder (Builder, char7, toLazyByteString)+import Data.Int+import Data.Scientific (Scientific)+import Data.Semigroup (Semigroup ((<>)))+import Data.Text (Text)+import Data.Time (Day, LocalTime, TimeOfDay, UTCTime, ZonedTime)+import Data.Typeable (Typeable)+import Data.Word+import qualified Data.Aeson.Encoding.Builder as EB+import qualified Data.ByteString.Builder as B+import qualified Data.ByteString.Lazy as BSL+import qualified Data.Text.Lazy as LT++-- | An encoding of a JSON value.+--+-- @tag@ represents which kind of JSON the Encoding is encoding to,+-- we reuse 'Text' and 'Value' as tags here.+newtype Encoding' tag = Encoding {+      fromEncoding :: Builder+      -- ^ Acquire the underlying bytestring builder.+    } deriving (Typeable)++-- | Often used synonnym for 'Encoding''.+type Encoding = Encoding' Value++-- | Make Encoding from Builder.+--+-- Use with care! You have to make sure that the passed Builder+-- is a valid JSON Encoding!+unsafeToEncoding :: Builder -> Encoding' a+unsafeToEncoding = Encoding++encodingToLazyByteString :: Encoding' a -> BSL.ByteString+encodingToLazyByteString = toLazyByteString . fromEncoding+{-# INLINE encodingToLazyByteString #-}++retagEncoding :: Encoding' a -> Encoding' b+retagEncoding = Encoding . fromEncoding++-------------------------------------------------------------------------------+-- Encoding instances+-------------------------------------------------------------------------------++instance Show (Encoding' a) where+    show (Encoding e) = show (toLazyByteString e)++instance Eq (Encoding' a) where+    Encoding a == Encoding b = toLazyByteString a == toLazyByteString b++instance Ord (Encoding' a) where+    compare (Encoding a) (Encoding b) =+      compare (toLazyByteString a) (toLazyByteString b)++-- | A series of values that, when encoded, should be separated by+-- commas. Since 0.11.0.0, the '.=' operator is overloaded to create+-- either @(Text, Value)@ or 'Series'. You can use Series when+-- encoding directly to a bytestring builder as in the following+-- example:+--+-- > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)+data Series = Empty+            | Value (Encoding' Series)+            deriving (Typeable)++pair :: Text -> Encoding -> Series+pair name val = Value $ retagEncoding $ text name >< colon >< val++instance Semigroup Series where+    Empty   <> a       = a+    a       <> Empty   = a+    Value a <> Value b = Value (a >< comma >< b)++instance Monoid Series where+    mempty  = Empty+    mappend = (<>)++nullEncoding :: Encoding' a -> Bool+nullEncoding = BSL.null . toLazyByteString . fromEncoding++emptyArray_ :: Encoding+emptyArray_ = Encoding EB.emptyArray_++emptyObject_ :: Encoding+emptyObject_ = Encoding EB.emptyObject_++wrapArray :: Encoding' a -> Encoding+wrapArray e = retagEncoding $ openBracket >< e >< closeBracket++wrapObject :: Encoding' a -> Encoding+wrapObject e = retagEncoding $ openCurly >< e >< closeCurly++null_ :: Encoding+null_ = Encoding EB.null_++bool :: Bool -> Encoding+bool True = Encoding "true"+bool False = Encoding "false"++-- | Encode a series of key/value pairs, separated by commas.+pairs :: Series -> Encoding+pairs (Value v) = openCurly >< retagEncoding v >< closeCurly+pairs Empty     = emptyObject_+{-# INLINE pairs #-}++list :: (a -> Encoding) -> [a] -> Encoding+list _  []     = emptyArray_+list to' (x:xs) = openBracket >< to' x >< commas xs >< closeBracket+  where+    commas = foldr (\v vs -> comma >< to' v >< vs) empty+{-# INLINE list #-}++-- | Encode as JSON object+dict+    :: (k -> Encoding' Text)                     -- ^ key encoding+    -> (v -> Encoding)                                -- ^ value encoding+    -> (forall a. (k -> v -> a -> a) -> a -> m -> a)  -- ^ @foldrWithKey@ - indexed fold+    -> m                                              -- ^ container+    -> Encoding+dict encodeKey encodeVal foldrWithKey = pairs . foldrWithKey go mempty+  where+    go k v c = Value (encodeKV k v) <> c+    encodeKV k v = retagEncoding (encodeKey k) >< colon >< retagEncoding (encodeVal v)+{-# INLINE dict #-}++-- | Type tag for tuples contents, see 'tuple'.+data InArray++infixr 6 >*<+-- | See 'tuple'.+(>*<) :: Encoding' a -> Encoding' b -> Encoding' InArray+a >*< b = retagEncoding a >< comma >< retagEncoding b+{-# INLINE (>*<) #-}++empty :: Encoding' a+empty = Encoding mempty++econcat :: [Encoding' a] -> Encoding' a+econcat = foldr (><) empty++infixr 6 ><+(><) :: Encoding' a -> Encoding' a -> Encoding' a+Encoding a >< Encoding b = Encoding (a <> b)+{-# INLINE (><) #-}++-- | Encode as a tuple.+--+-- @+-- toEncoding (X a b c) = tuple $+--     toEncoding a >*<+--     toEncoding b >*<+--     toEncoding c+tuple :: Encoding' InArray -> Encoding+tuple b = retagEncoding $ openBracket >< b >< closeBracket+{-# INLINE tuple #-}++text :: Text -> Encoding' a+text = Encoding . EB.text++lazyText :: LT.Text -> Encoding' a+lazyText t = Encoding $+    B.char7 '"' <>+    LT.foldrChunks (\x xs -> EB.unquoted x <> xs) (B.char7 '"') t++string :: String -> Encoding' a+string = Encoding . EB.string++-------------------------------------------------------------------------------+-- chars+-------------------------------------------------------------------------------++comma, colon, openBracket, closeBracket, openCurly, closeCurly :: Encoding' a+comma        = Encoding $ char7 ','+colon        = Encoding $ char7 ':'+openBracket  = Encoding $ char7 '['+closeBracket = Encoding $ char7 ']'+openCurly    = Encoding $ char7 '{'+closeCurly   = Encoding $ char7 '}'++-------------------------------------------------------------------------------+-- Decimal numbers+-------------------------------------------------------------------------------++int8 :: Int8 -> Encoding+int8 = Encoding . B.int8Dec++int16 :: Int16 -> Encoding+int16 = Encoding . B.int16Dec++int32 :: Int32 -> Encoding+int32 = Encoding . B.int32Dec++int64 :: Int64 -> Encoding+int64 = Encoding . B.int64Dec++int :: Int -> Encoding+int = Encoding . B.intDec++word8 :: Word8 -> Encoding+word8 = Encoding . B.word8Dec++word16 :: Word16 -> Encoding+word16 = Encoding . B.word16Dec++word32 :: Word32 -> Encoding+word32 = Encoding . B.word32Dec++word64 :: Word64 -> Encoding+word64 = Encoding . B.word64Dec++word :: Word -> Encoding+word = Encoding . B.wordDec++integer :: Integer -> Encoding+integer = Encoding . B.integerDec++float :: Float -> Encoding+float = realFloatToEncoding $ Encoding . B.floatDec++double :: Double -> Encoding+double = realFloatToEncoding $ Encoding . B.doubleDec++scientific :: Scientific -> Encoding+scientific = Encoding . EB.scientific++realFloatToEncoding :: RealFloat a => (a -> Encoding) -> a -> Encoding+realFloatToEncoding e d+    | isNaN d || isInfinite d = null_+    | otherwise               = e d+{-# INLINE realFloatToEncoding #-}++-------------------------------------------------------------------------------+-- Decimal numbers as Text+-------------------------------------------------------------------------------++int8Text :: Int8 -> Encoding' a+int8Text = Encoding . EB.quote . B.int8Dec++int16Text :: Int16 -> Encoding' a+int16Text = Encoding . EB.quote . B.int16Dec++int32Text :: Int32 -> Encoding' a+int32Text = Encoding . EB.quote . B.int32Dec++int64Text :: Int64 -> Encoding' a+int64Text = Encoding . EB.quote . B.int64Dec++intText :: Int -> Encoding' a+intText = Encoding . EB.quote . B.intDec++word8Text :: Word8 -> Encoding' a+word8Text = Encoding . EB.quote . B.word8Dec++word16Text :: Word16 -> Encoding' a+word16Text = Encoding . EB.quote . B.word16Dec++word32Text :: Word32 -> Encoding' a+word32Text = Encoding . EB.quote . B.word32Dec++word64Text :: Word64 -> Encoding' a+word64Text = Encoding . EB.quote . B.word64Dec++wordText :: Word -> Encoding' a+wordText = Encoding . EB.quote . B.wordDec++integerText :: Integer -> Encoding' a+integerText = Encoding . EB.quote . B.integerDec++floatText :: Float -> Encoding' a+floatText = Encoding . EB.quote . B.floatDec++doubleText :: Double -> Encoding' a+doubleText = Encoding . EB.quote . B.doubleDec++scientificText :: Scientific -> Encoding' a+scientificText = Encoding . EB.quote . EB.scientific++-------------------------------------------------------------------------------+-- time+-------------------------------------------------------------------------------++day :: Day -> Encoding' a+day = Encoding . EB.quote . EB.day++localTime :: LocalTime -> Encoding' a+localTime = Encoding . EB.quote . EB.localTime++utcTime :: UTCTime -> Encoding' a+utcTime = Encoding . EB.quote . EB.utcTime++timeOfDay :: TimeOfDay -> Encoding' a+timeOfDay = Encoding . EB.quote . EB.timeOfDay++zonedTime :: ZonedTime -> Encoding' a+zonedTime = Encoding . EB.quote . EB.zonedTime++-------------------------------------------------------------------------------+-- Value+-------------------------------------------------------------------------------++value :: Value -> Encoding+value = Encoding . EB.encodeToBuilder
− Data/Aeson/Functions.hs
@@ -1,42 +0,0 @@--- |--- Module:      Data.Aeson.Functions--- Copyright:   (c) 2011-2016 Bryan O'Sullivan---              (c) 2011 MailRank, Inc.--- License:     BSD3--- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>--- Stability:   experimental--- Portability: portable--module Data.Aeson.Functions-    ( mapHashKeyVal-    , hashMapKey-    , mapKeyVal-    , mapKey-    ) where--import Data.Hashable (Hashable)-import qualified Data.HashMap.Strict as H-import qualified Data.Map as M---- | Transform a 'M.Map' into a 'H.HashMap' while transforming the keys.-mapHashKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)-              -> M.Map k1 v1 -> H.HashMap k2 v2-mapHashKeyVal fk kv = M.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty-{-# INLINE mapHashKeyVal #-}---- | Transform a 'M.Map' into a 'H.HashMap' while transforming the keys.-hashMapKey :: (Ord k2) => (k1 -> k2)-           -> H.HashMap k1 v -> M.Map k2 v-hashMapKey kv = H.foldrWithKey (M.insert . kv) M.empty-{-# INLINE hashMapKey #-}---- | Transform the keys and values of a 'H.HashMap'.-mapKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)-          -> H.HashMap k1 v1 -> H.HashMap k2 v2-mapKeyVal fk kv = H.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty-{-# INLINE mapKeyVal #-}---- | Transform the keys of a 'H.HashMap'.-mapKey :: (Eq k2, Hashable k2) => (k1 -> k2) -> H.HashMap k1 v -> H.HashMap k2 v-mapKey fk = mapKeyVal fk id-{-# INLINE mapKey #-}
Data/Aeson/Internal.hs view
@@ -22,5 +22,7 @@     , iparse     ) where -import Data.Aeson.Types.Instances (ifromJSON)+import Prelude ()+ import Data.Aeson.Types.Internal+import Data.Aeson.Types.FromJSON (ifromJSON)
+ Data/Aeson/Internal/Functions.hs view
@@ -0,0 +1,39 @@+-- |+-- Module:      Data.Aeson.Functions+-- Copyright:   (c) 2011-2016 Bryan O'Sullivan+--              (c) 2011 MailRank, Inc.+-- License:     BSD3+-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>+-- Stability:   experimental+-- Portability: portable++module Data.Aeson.Internal.Functions+    (+      mapHashKeyVal+    , mapKeyVal+    , mapKey+    ) where++import Prelude ()+import Prelude.Compat++import Data.Hashable (Hashable)+import qualified Data.HashMap.Strict as H+import qualified Data.Map as M++-- | Transform a 'M.Map' into a 'H.HashMap' while transforming the keys.+mapHashKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)+              -> M.Map k1 v1 -> H.HashMap k2 v2+mapHashKeyVal fk kv = M.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty+{-# INLINE mapHashKeyVal #-}++-- | Transform the keys and values of a 'H.HashMap'.+mapKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)+          -> H.HashMap k1 v1 -> H.HashMap k2 v2+mapKeyVal fk kv = H.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty+{-# INLINE mapKeyVal #-}++-- | Transform the keys of a 'H.HashMap'.+mapKey :: (Eq k2, Hashable k2) => (k1 -> k2) -> H.HashMap k1 v -> H.HashMap k2 v+mapKey fk = mapKeyVal fk id+{-# INLINE mapKey #-}
Data/Aeson/Internal/Time.hs view
@@ -17,6 +17,9 @@     , toTimeOfDay64     ) where +import Prelude ()+import Prelude.Compat+ import Data.Fixed (Pico) import Data.Int (Int64) import Data.Time
Data/Aeson/Parser.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}  -- | -- Module:      Data.Aeson.Parser@@ -39,9 +39,16 @@     -- $strict     , json'     , value'+    -- * Decoding without FromJSON instances+    , decodeWith+    , decodeStrictWith+    , eitherDecodeWith+    , eitherDecodeStrictWith     ) where -import Data.Aeson.Parser.Internal (json, json', jstring, value, value')+import Prelude ()++import Data.Aeson.Parser.Internal (decodeStrictWith, decodeWith, eitherDecodeStrictWith, eitherDecodeWith, json, json', jstring, value, value')  -- $lazy --
Data/Aeson/Parser/Internal.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE BangPatterns, CPP, OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} #if MIN_VERSION_ghc_prim(0,3,1) {-# LANGUAGE MagicHash #-} #endif@@ -31,10 +33,12 @@     , eitherDecodeStrictWith     ) where +import Prelude ()+import Prelude.Compat+ import Control.Monad.IO.Class (liftIO) import Data.Aeson.Types.Internal (IResult(..), JSONPath, Result(..), Value(..))-import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific,-                                         skipSpace, string)+import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific, skipSpace, string) import Data.Bits ((.|.), shiftL) import Data.ByteString.Internal (ByteString(..)) import Data.Char (chr)@@ -45,8 +49,8 @@ import Data.Vector as Vector (Vector, empty, fromList, reverse) import Data.Word (Word8) import Foreign.ForeignPtr (withForeignPtr)-import Foreign.Ptr (Ptr, plusPtr)-import Foreign.Ptr (minusPtr)+import Foreign.Marshal.Utils (copyBytes)+import Foreign.Ptr (Ptr, minusPtr, plusPtr) import Foreign.Storable (poke) import System.IO.Unsafe (unsafePerformIO) import qualified Data.Attoparsec.ByteString as A@@ -58,10 +62,6 @@ import qualified Data.ByteString.Unsafe as B import qualified Data.HashMap.Strict as H -#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((*>), (<$>), (<*), pure)-#endif- #if MIN_VERSION_ghc_prim(0,3,1) import GHC.Base (Int#, (==#), isTrue#, orI#, word2Int#) import GHC.Word (Word8(W8#))@@ -263,7 +263,7 @@         let newlen = p `minusPtr` ptr             slop = len - newlen         Right <$> if slop >= 128 && slop >= len `quot` 4-                  then B.create newlen $ \np -> B.memcpy np ptr newlen+                  then B.create newlen $ \np -> copyBytes np ptr newlen                   else return (PS fp 0 newlen)  where   go ptr = do@@ -382,7 +382,7 @@ copy :: ByteString -> Ptr Word8 -> Z.ZeptoT IO (Ptr Word8) copy (PS fp off len) ptr =   liftIO . withForeignPtr fp $ \src -> do-    B.memcpy ptr (src `plusPtr` off) len+    copyBytes ptr (src `plusPtr` off) len     return $! ptr `plusPtr` len  charUtf8 :: Char -> Ptr Word8 -> Z.ZeptoT IO (Ptr Word8)
Data/Aeson/Parser/Time.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}  -- | -- Module:      Data.Aeson.Parser.Time@@ -21,7 +22,10 @@     , zonedTime     ) where -import Control.Monad (when, void)+import Prelude ()+import Prelude.Compat++import Control.Monad (void, when) import Data.Aeson.Internal.Time (toPico) import Data.Attoparsec.Text as A import Data.Bits ((.&.))@@ -35,10 +39,6 @@ import qualified Data.Aeson.Types.Internal as Aeson import qualified Data.Text as T import qualified Data.Time.LocalTime as Local--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>), (<*>), (<*), (*>))-#endif  -- | Run an attoparsec parser as an aeson parser. run :: Parser a -> Text -> Aeson.Parser a
Data/Aeson/TH.hs view
@@ -1,1512 +1,2441 @@-{-# LANGUAGE CPP, FlexibleInstances, NamedFieldPuns,-    NoImplicitPrelude, UndecidableInstances #-}-#if __GLASGOW_HASKELL__ >= 800--- a) THQ works on cross-compilers and unregisterised GHCs--- b) may make compilation faster as no dynamic loading is ever needed (not sure about this)--- c) removes one hindrance to have code inferred as SafeHaskell safe-{-# LANGUAGE TemplateHaskellQuotes #-}-#else-{-# LANGUAGE TemplateHaskell #-}-#endif--#include "overlapping-compat.h"--{-|-Module:      Data.Aeson.TH-Copyright:   (c) 2011-2016 Bryan O'Sullivan-             (c) 2011 MailRank, Inc.-License:     BSD3-Stability:   experimental-Portability: portable--Functions to mechanically derive 'ToJSON' and 'FromJSON' instances. Note that-you need to enable the @TemplateHaskell@ language extension in order to use this-module.--An example shows how instances are generated for arbitrary data types. First we-define a data type:--@-data D a = Nullary-         | Unary Int-         | Product String Char a-         | Record { testOne   :: Double-                  , testTwo   :: Bool-                  , testThree :: D a-                  } deriving Eq-@--Next we derive the necessary instances. Note that we make use of the-feature to change record field names. In this case we drop the first 4-characters of every field name. We also modify constructor names by-lower-casing them:--@-$('deriveJSON' 'defaultOptions'{'fieldLabelModifier' = 'drop' 4, 'constructorTagModifier' = map toLower} ''D)-@--Now we can use the newly created instances.--@-d :: D 'Int'-d = Record { testOne = 3.14159-           , testTwo = 'True'-           , testThree = Product \"test\" \'A\' 123-           }-@-->>> fromJSON (toJSON d) == Success d-> True--This also works for data family instances, but instead of passing in the data-family name (with double quotes), we pass in a data family instance-constructor (with a single quote):--@-data family DF a-data instance DF Int = DF1 Int-                     | DF2 Int Int-                     deriving Eq--$('deriveJSON' 'defaultOptions' 'DF1)--- Alternatively, one could pass 'DF2 instead-@--Please note that you can derive instances for tuples using the following syntax:--@--- FromJSON and ToJSON instances for 4-tuples.-$('deriveJSON' 'defaultOptions' ''(,,,))-@---}--module Data.Aeson.TH-    ( -- * Encoding configuration-      Options(..), SumEncoding(..), defaultOptions, defaultTaggedObject--     -- * FromJSON and ToJSON derivation-    , deriveJSON--    , deriveToJSON-    , deriveFromJSON--    , mkToJSON-    , mkToEncoding-    , mkParseJSON-    ) where--import Control.Applicative ( pure, (<$>), (<*>) )-import Data.Aeson ( toJSON, Object, (.=), (.:), (.:?)-                  , ToJSON, toEncoding, toJSON-                  , FromJSON, parseJSON-                  )-import Data.Aeson.Types ( Value(..), Parser-                        , Options(..)-                        , SumEncoding(..)-                        , defaultOptions-                        , defaultTaggedObject-                        )-import Data.Aeson.Types.Internal (Encoding(..))-import Control.Monad       ( liftM2, return, mapM, fail )-import Data.Bool           ( Bool(False, True), otherwise, (&&), not )-import Data.Either         ( Either(Left, Right) )-import Data.Eq             ( (==) )-import Data.Function       ( ($), (.), flip )-import Data.Functor        ( fmap )-import Data.Int            ( Int )-import Data.List           ( (++), all, any, find, foldl, foldl'-                           , genericLength , intercalate , intersperse, length, map-                           , partition, zip-                           )-import Data.Map            ( Map )-import Data.Maybe          ( Maybe(Nothing, Just), catMaybes )-import Data.Monoid         ( (<>), mconcat )-import Language.Haskell.TH-import Language.Haskell.TH.Syntax ( VarStrictType )-import Prelude             ( String, (-), Integer, error, foldr1, fromIntegral-                           , splitAt, zipWith-                           )-#if MIN_VERSION_template_haskell(2,8,0) && !(MIN_VERSION_template_haskell(2,10,0))-import Data.Foldable              ( foldr' )-import qualified Data.Map as M    ( singleton )-import Data.List                  ( nub )-import Language.Haskell.TH.Syntax ( mkNameG_tc )-import Prelude                    ( concatMap, uncurry )-#endif-#if MIN_VERSION_template_haskell(2,11,0)-import Prelude             ( head )-#endif-import Text.Printf         ( printf )-import Text.Show           ( show )-import qualified Data.Aeson as A-import qualified Data.Aeson.Encode.Builder as E-import qualified Data.Aeson.Encode.Functions as E-import qualified Data.HashMap.Strict as H ( lookup, toList )-import qualified Data.Map as M ( fromList, findWithDefault )-import qualified Data.Text as T ( Text, pack, unpack )-import qualified Data.Vector as V ( unsafeIndex, null, length, create, fromList )-import qualified Data.Vector.Mutable as VM ( unsafeNew, unsafeWrite )-------------------------------------------------------------------------------------- Convenience------------------------------------------------------------------------------------- | Generates both 'ToJSON' and 'FromJSON' instance declarations for the given--- data type or data family instance constructor.------ This is a convienience function which is equivalent to calling both--- 'deriveToJSON' and 'deriveFromJSON'.-deriveJSON :: Options-           -- ^ Encoding options.-           -> Name-           -- ^ Name of the type for which to generate 'ToJSON' and 'FromJSON'-           -- instances.-           -> Q [Dec]-deriveJSON opts name =-    liftM2 (++)-           (deriveToJSON   opts name)-           (deriveFromJSON opts name)-------------------------------------------------------------------------------------- ToJSON-----------------------------------------------------------------------------------{--TODO: Don't constrain phantom type variables.--data Foo a = Foo Int-instance (ToJSON a) ⇒ ToJSON Foo where ...--The above (ToJSON a) constraint is not necessary and perhaps undesirable.--}---- | Generates a 'ToJSON' instance declaration for the given data type or--- data family instance constructor.-deriveToJSON :: Options-             -- ^ Encoding options.-             -> Name-             -- ^ Name of the type for which to generate a 'ToJSON' instance-             -- declaration.-             -> Q [Dec]-deriveToJSON opts name =-    withType name $ \name' tvbs cons mbTys -> fmap (:[]) $ fromCons name' tvbs cons mbTys-  where-    fromCons :: Name -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Dec-    fromCons name' tvbs cons mbTys = do-        (instanceCxt, instanceType) <- buildTypeInstance name' ''ToJSON tvbs mbTys-        instanceD (return instanceCxt)-                  (return instanceType)-                  [ funD 'toJSON-                         [ clause []-                                  (normalB $ consToValue opts cons)-                                  []-                         ]-                  , funD 'toEncoding-                         [ clause []-                                  (normalB $ consToEncoding opts cons)-                                  []-                         ]-                  ]---- | Generates a lambda expression which encodes the given data type or--- data family instance constructor as a 'Value'.-mkToJSON :: Options -- ^ Encoding options.-         -> Name -- ^ Name of the type to encode.-         -> Q Exp-mkToJSON opts name = withType name (\_ _ cons _ -> consToValue opts cons)---- | Generates a lambda expression which encodes the given data type or--- data family instance constructor as a JSON string.-mkToEncoding :: Options -- ^ Encoding options.-             -> Name -- ^ Name of the type to encode.-             -> Q Exp-mkToEncoding opts name = withType name (\_ _ cons _ -> consToEncoding opts cons)---- | Helper function used by both 'deriveToJSON' and 'mkToJSON'. Generates--- code to generate a 'Value' of a number of constructors. All constructors--- must be from the same type.-consToValue :: Options-           -- ^ Encoding options.-           -> [Con]-           -- ^ Constructors for which to generate JSON generating code.-           -> Q Exp--consToValue _ [] = error $ "Data.Aeson.TH.consToValue: "-                          ++ "Not a single constructor given!"---- A single constructor is directly encoded. The constructor itself may be--- forgotten.-consToValue opts [con] = do-    value <- newName "value"-    lam1E (varP value) $ caseE (varE value) [argsToValue opts False con]--consToValue opts cons = do-    value <- newName "value"-    lam1E (varP value) $ caseE (varE value) matches-  where-    matches-        | allNullaryToStringTag opts && all isNullary cons =-              [ match (conP conName []) (normalB $ conStr opts conName) []-              | con <- cons-              , let conName = getConName con-              ]-        | otherwise = [argsToValue opts True con | con <- cons]--conStr :: Options -> Name -> Q Exp-conStr opts = appE [|String|] . conTxt opts--conTxt :: Options -> Name -> Q Exp-conTxt opts = appE [|T.pack|] . conStringE opts--conStringE :: Options -> Name -> Q Exp-conStringE opts = stringE . constructorTagModifier opts . nameBase---- | Helper function used by both 'deriveToJSON' and 'mkToEncoding'. Generates--- code to write out a value for a number of constructors. All constructors--- must be from the same type.-consToEncoding :: Options-                  -- ^ Encoding options.-               -> [Con]-               -- ^ Constructors for which to generate JSON generating code.-               -> Q Exp--consToEncoding _ [] = error $ "Data.Aeson.TH.consToEncoding: "-                      ++ "Not a single constructor given!"---- A single constructor is directly encoded. The constructor itself may be--- forgotten.-consToEncoding opts [con] = do-    value <- newName "value"-    lam1E (varP value) $ caseE (varE value) [argsToEncoding opts False con]---- Encode just the name of the constructor of a sum type iff all the--- constructors are nullary.-consToEncoding opts cons = do-    value <- newName "value"-    lam1E (varP value) $ caseE (varE value) matches-  where-    matches-        | allNullaryToStringTag opts && all isNullary cons =-              [ match (conP conName [])-                (normalB $ [|Encoding|] `appE` encStr opts conName) []-              | con <- cons-              , let conName = getConName con-              ]-        | otherwise = [argsToEncoding opts True con | con <- cons]--encStr :: Options -> Name -> Q Exp-encStr opts = appE [|E.text|] . conTxt opts---- | If constructor is nullary.-isNullary :: Con -> Bool-isNullary (NormalC _ []) = True-isNullary _ = False--sumToValue :: Options -> Bool -> Name -> Q Exp -> Q Exp-sumToValue opts multiCons conName exp-    | multiCons =-        case sumEncoding opts of-          TwoElemArray ->-              [|Array|] `appE` ([|V.fromList|] `appE` listE [conStr opts conName, exp])-          TaggedObject{tagFieldName, contentsFieldName} ->-              [|A.object|] `appE` listE-                [ infixApp [|T.pack tagFieldName|]     [|(.=)|] (conStr opts conName)-                , infixApp [|T.pack contentsFieldName|] [|(.=)|] exp-                ]-          ObjectWithSingleField ->-              [|A.object|] `appE` listE-                [ infixApp (conTxt opts conName) [|(.=)|] exp-                ]--    | otherwise = exp---- | Generates code to generate the JSON encoding of a single constructor.-argsToValue :: Options -> Bool -> Con -> Q Match--- Nullary constructors. Generates code that explicitly matches against the--- constructor even though it doesn't contain data. This is useful to prevent--- type errors.-argsToValue  opts multiCons (NormalC conName []) =-    match (conP conName [])-          (normalB (sumToValue opts multiCons conName [e|toJSON ([] :: [()])|]))-          []---- Polyadic constructors with special case for unary constructors.-argsToValue opts multiCons (NormalC conName ts) = do-    let len = length ts-    args <- mapM newName ["arg" ++ show n | n <- [1..len]]-    js <- case [[|toJSON|] `appE` varE arg | arg <- args] of-            -- Single argument is directly converted.-            [e] -> return e-            -- Multiple arguments are converted to a JSON array.-            es  -> do-              mv <- newName "mv"-              let newMV = bindS (varP mv)-                                ([|VM.unsafeNew|] `appE`-                                  litE (integerL $ fromIntegral len))-                  stmts = [ noBindS $-                              [|VM.unsafeWrite|] `appE`-                                (varE mv) `appE`-                                  litE (integerL ix) `appE`-                                    e-                          | (ix, e) <- zip [(0::Integer)..] es-                          ]-                  ret = noBindS $ [|return|] `appE` varE mv-              return $ [|Array|] `appE`-                         (varE 'V.create `appE`-                           doE (newMV:stmts++[ret]))-    match (conP conName $ map varP args)-          (normalB $ sumToValue opts multiCons conName js)-          []---- Records.-argsToValue opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of-  (True,True,[(_,st,ty)]) -> argsToValue opts multiCons (NormalC conName [(st,ty)])-  _ -> do-    args <- mapM newName ["arg" ++ show n | (_, n) <- zip ts [1 :: Integer ..]]-    let exp = [|A.object|] `appE` pairs--        pairs | omitNothingFields opts = infixApp maybeFields-                                                  [|(++)|]-                                                  restFields-              | otherwise = listE $ map toPair argCons--        argCons = zip args ts--        maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)--        restFields = listE $ map toPair rest--        (maybes, rest) = partition isMaybe argCons--        maybeToPair (arg, (field, _, _)) =-            infixApp (infixE (Just $ toFieldName field)-                             [|(.=)|]-                             Nothing)-                     [|(<$>)|]-                     (varE arg)--        toPair (arg, (field, _, _)) =-            infixApp (toFieldName field)-                     [|(.=)|]-                     (varE arg)--        toFieldName field = [|T.pack|] `appE` fieldLabelExp opts field--    match (conP conName $ map varP args)-          ( normalB-          $ if multiCons-            then case sumEncoding opts of-                   TwoElemArray -> [|toJSON|] `appE` tupE [conStr opts conName, exp]-                   TaggedObject{tagFieldName} ->-                       [|A.object|] `appE`-                         -- TODO: Maybe throw an error in case-                         -- tagFieldName overwrites a field in pairs.-                         infixApp (infixApp [|T.pack tagFieldName|]-                                            [|(.=)|]-                                            (conStr opts conName))-                                  [|(:)|]-                                  pairs-                   ObjectWithSingleField ->-                       [|A.object|] `appE` listE-                         [ infixApp (conTxt opts conName) [|(.=)|] exp ]-            else exp-          ) []---- Infix constructors.-argsToValue opts multiCons (InfixC _ conName _) = do-    al <- newName "argL"-    ar <- newName "argR"-    match (infixP (varP al) conName (varP ar))-          ( normalB-          $ sumToValue opts multiCons conName-          $ [|toJSON|] `appE` listE [ [|toJSON|] `appE` varE a-                                    | a <- [al,ar]-                                    ]-          )-          []--- Existentially quantified constructors.-argsToValue opts multiCons (ForallC _ _ con) =-    argsToValue opts multiCons con--#if MIN_VERSION_template_haskell(2,11,0)--- GADTs.-argsToValue opts multiCons (GadtC conNames ts _) =-    argsToValue opts multiCons $ NormalC (head conNames) ts--argsToValue opts multiCons (RecGadtC conNames ts _) =-    argsToValue opts multiCons $ RecC (head conNames) ts-#endif--isMaybe :: (a, (b, c, Type)) -> Bool-isMaybe (_, (_, _, AppT (ConT t) _)) = t == ''Maybe-isMaybe _                            = False--(<^>) :: ExpQ -> ExpQ -> ExpQ-(<^>) a b = infixApp a [|(<>)|] b-infixr 6 <^>--(<:>) :: ExpQ -> ExpQ -> ExpQ-(<:>) a b = a <^> [|E.char7 ':'|] <^> b-infixr 5 <:>--(<%>) :: ExpQ -> ExpQ -> ExpQ-(<%>) a b = a <^> [|E.char7 ','|] <^> b-infixr 4 <%>--array :: ExpQ -> ExpQ-array exp = [|Encoding|] `appE` ([|E.char7 '['|] <^> exp <^> [|E.char7 ']'|])--object :: ExpQ -> ExpQ-object exp = [|Encoding|] `appE` ([|E.char7 '{'|] <^> exp <^> [|E.char7 '}'|])--sumToEncoding :: Options -> Bool -> Name -> Q Exp -> Q Exp-sumToEncoding opts multiCons conName exp-    | multiCons =-        let fexp = [|fromEncoding|] `appE` exp in-        case sumEncoding opts of-          TwoElemArray ->-            array (encStr opts conName <%> fexp)-          TaggedObject{tagFieldName, contentsFieldName} ->-            object $-            ([|E.text (T.pack tagFieldName)|] <:> encStr opts conName) <%>-            ([|E.text (T.pack contentsFieldName)|] <:> fexp)-          ObjectWithSingleField ->-            object (encStr opts conName <:> fexp)--    | otherwise = exp---- | Generates code to generate the JSON encoding of a single constructor.-argsToEncoding :: Options -> Bool -> Con -> Q Match--- Nullary constructors. Generates code that explicitly matches against the--- constructor even though it doesn't contain data. This is useful to prevent--- type errors.-argsToEncoding  opts multiCons (NormalC conName []) =-    match (conP conName [])-          (normalB (sumToEncoding opts multiCons conName [e|toEncoding ([] :: [()])|]))-          []---- Polyadic constructors with special case for unary constructors.-argsToEncoding opts multiCons (NormalC conName ts) = do-    let len = length ts-    args <- mapM newName ["arg" ++ show n | n <- [1..len]]-    js <- case args of-            -- Single argument is directly converted.-            [e] -> return ([|toEncoding|] `appE` varE e)-            -- Multiple arguments are converted to a JSON array.-            es  ->-              return (array (foldr1 (<%>) [[|E.builder|] `appE` varE x | x <- es]))-    match (conP conName $ map varP args)-          (normalB $ sumToEncoding opts multiCons conName js)-          []---- Records.-argsToEncoding opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of-  (True,True,[(_,st,ty)]) -> argsToEncoding opts multiCons (NormalC conName [(st,ty)])-  _ -> do-    args <- mapM newName ["arg" ++ show n | (_, n) <- zip ts [1 :: Integer ..]]--    let exp = object objBody--        objBody = [|mconcat|] `appE`-                  ([|intersperse (E.char7 ',')|] `appE` pairs)-        pairs | omitNothingFields opts = infixApp maybeFields-                                                  [|(<>)|]-                                                  restFields-              | otherwise = listE (map toPair argCons)--        argCons = zip args ts--        maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)--        restFields = listE (map toPair rest)--        (maybes, rest) = partition isMaybe argCons--        maybeToPair (arg, (field, _, _)) =-            infixApp-              (infixApp-                (infixE-                  (Just $ toFieldName field <^> [|E.char7 ':'|])-                  [|(<>)|]-                  Nothing)-                [|(.)|]-                [|E.builder|])-              [|(<$>)|]-              (varE arg)--        toPair (arg, (field, _, _)) =-          toFieldName field <:> [|E.builder|] `appE` varE arg--        toFieldName field = [|E.text|] `appE`-                            ([|T.pack|] `appE` fieldLabelExp opts field)--    match (conP conName $ map varP args)-          ( normalB-          $ if multiCons-            then case sumEncoding opts of-                   TwoElemArray -> array $-                     encStr opts conName <%> [|fromEncoding|] `appE` exp-                   TaggedObject{tagFieldName} -> object $-                     ([|E.text (T.pack tagFieldName)|] <:>-                      encStr opts conName) <%>-                     objBody-                   ObjectWithSingleField -> object $-                     encStr opts conName <:> [|fromEncoding|] `appE` exp-            else exp-          ) []---- Infix constructors.-argsToEncoding opts multiCons (InfixC _ conName _) = do-    al <- newName "argL"-    ar <- newName "argR"-    match (infixP (varP al) conName (varP ar))-          ( normalB-          $ sumToEncoding opts multiCons conName-          $ [|toEncoding|] `appE` listE [ [|toJSON|] `appE` varE a-                                        | a <- [al,ar]-                                        ]-          )-          []--- Existentially quantified constructors.-argsToEncoding opts multiCons (ForallC _ _ con) =-    argsToEncoding opts multiCons con--#if MIN_VERSION_template_haskell(2,11,0)--- GADTs.-argsToEncoding opts multiCons (GadtC conNames ts _) =-    argsToEncoding opts multiCons $ NormalC (head conNames) ts--argsToEncoding opts multiCons (RecGadtC conNames ts _) =-    argsToEncoding opts multiCons $ RecC (head conNames) ts-#endif------------------------------------------------------------------------------------- FromJSON------------------------------------------------------------------------------------- | Generates a 'FromJSON' instance declaration for the given data type or--- data family instance constructor.-deriveFromJSON :: Options-               -- ^ Encoding options.-               -> Name-               -- ^ Name of the type for which to generate a 'FromJSON' instance-               -- declaration.-               -> Q [Dec]-deriveFromJSON opts name =-    withType name $ \name' tvbs cons mbTys -> fmap (:[]) $ fromCons name' tvbs cons mbTys-  where-    fromCons :: Name -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Dec-    fromCons name' tvbs cons mbTys = do-        (instanceCxt, instanceType) <- buildTypeInstance name' ''FromJSON tvbs mbTys-        instanceD (return instanceCxt)-                  (return instanceType)-                  [ funD 'parseJSON-                         [ clause []-                                  (normalB $ consFromJSON name' opts cons)-                                  []-                         ]-                  ]---- | Generates a lambda expression which parses the JSON encoding of the given--- data type or data family instance constructor.-mkParseJSON :: Options -- ^ Encoding options.-            -> Name -- ^ Name of the encoded type.-            -> Q Exp-mkParseJSON opts name =-    withType name (\name' _ cons _ -> consFromJSON name' opts cons)---- | Helper function used by both 'deriveFromJSON' and 'mkParseJSON'. Generates--- code to parse the JSON encoding of a number of constructors. All constructors--- must be from the same type.-consFromJSON :: Name-             -- ^ Name of the type to which the constructors belong.-             -> Options-             -- ^ Encoding options-             -> [Con]-             -- ^ Constructors for which to generate JSON parsing code.-             -> Q Exp--consFromJSON _ _ [] = error $ "Data.Aeson.TH.consFromJSON: "-                              ++ "Not a single constructor given!"--consFromJSON tName opts [con] = do-  value <- newName "value"-  lam1E (varP value) (parseArgs tName opts con (Right value))--consFromJSON tName opts cons = do-  value <- newName "value"-  lam1E (varP value) $ caseE (varE value) $-    if allNullaryToStringTag opts && all isNullary cons-    then allNullaryMatches-    else mixedMatches--  where-    allNullaryMatches =-      [ do txt <- newName "txt"-           match (conP 'String [varP txt])-                 (guardedB $-                  [ liftM2 (,) (normalG $-                                  infixApp (varE txt)-                                           [|(==)|]-                                           ([|T.pack|] `appE`-                                              conStringE opts conName)-                               )-                               ([|pure|] `appE` conE conName)-                  | con <- cons-                  , let conName = getConName con-                  ]-                  ++-                  [ liftM2 (,)-                      (normalG [|otherwise|])-                      ( [|noMatchFail|]-                        `appE` (litE $ stringL $ show tName)-                        `appE` ([|T.unpack|] `appE` varE txt)-                      )-                  ]-                 )-                 []-      , do other <- newName "other"-           match (varP other)-                 (normalB $ [|noStringFail|]-                    `appE` (litE $ stringL $ show tName)-                    `appE` ([|valueConName|] `appE` varE other)-                 )-                 []-      ]--    mixedMatches =-        case sumEncoding opts of-          TaggedObject {tagFieldName, contentsFieldName} ->-            parseObject $ parseTaggedObject tagFieldName contentsFieldName-          ObjectWithSingleField ->-            parseObject $ parseObjectWithSingleField-          TwoElemArray ->-            [ do arr <- newName "array"-                 match (conP 'Array [varP arr])-                       (guardedB $-                        [ liftM2 (,) (normalG $ infixApp ([|V.length|] `appE` varE arr)-                                                         [|(==)|]-                                                         (litE $ integerL 2))-                                     (parse2ElemArray arr)-                        , liftM2 (,) (normalG [|otherwise|])-                                     (([|not2ElemArray|]-                                       `appE` (litE $ stringL $ show tName)-                                       `appE` ([|V.length|] `appE` varE arr)))-                        ]-                       )-                       []-            , do other <- newName "other"-                 match (varP other)-                       ( normalB-                         $ [|noArrayFail|]-                             `appE` (litE $ stringL $ show tName)-                             `appE` ([|valueConName|] `appE` varE other)-                       )-                       []-            ]--    parseObject f =-        [ do obj <- newName "obj"-             match (conP 'Object [varP obj]) (normalB $ f obj) []-        , do other <- newName "other"-             match (varP other)-                   ( normalB-                     $ [|noObjectFail|]-                         `appE` (litE $ stringL $ show tName)-                         `appE` ([|valueConName|] `appE` varE other)-                   )-                   []-        ]--    parseTaggedObject typFieldName valFieldName obj = do-      conKey <- newName "conKey"-      doE [ bindS (varP conKey)-                  (infixApp (varE obj)-                            [|(.:)|]-                            ([|T.pack|] `appE` stringE typFieldName))-          , noBindS $ parseContents conKey (Left (valFieldName, obj)) 'conNotFoundFailTaggedObject-          ]--    parse2ElemArray arr = do-      conKey <- newName "conKey"-      conVal <- newName "conVal"-      let letIx n ix =-              valD (varP n)-                   (normalB ([|V.unsafeIndex|] `appE`-                               varE arr `appE`-                               litE (integerL ix)))-                   []-      letE [ letIx conKey 0-           , letIx conVal 1-           ]-           (caseE (varE conKey)-                  [ do txt <- newName "txt"-                       match (conP 'String [varP txt])-                             (normalB $ parseContents txt-                                                      (Right conVal)-                                                      'conNotFoundFail2ElemArray-                             )-                             []-                  , do other <- newName "other"-                       match (varP other)-                             ( normalB-                               $ [|firstElemNoStringFail|]-                                     `appE` (litE $ stringL $ show tName)-                                     `appE` ([|valueConName|] `appE` varE other)-                             )-                             []-                  ]-           )--    parseObjectWithSingleField obj = do-      conKey <- newName "conKey"-      conVal <- newName "conVal"-      caseE ([e|H.toList|] `appE` varE obj)-            [ match (listP [tupP [varP conKey, varP conVal]])-                    (normalB $ parseContents conKey (Right conVal) 'conNotFoundFailObjectSingleField)-                    []-            , do other <- newName "other"-                 match (varP other)-                       (normalB $ [|wrongPairCountFail|]-                                  `appE` (litE $ stringL $ show tName)-                                  `appE` ([|show . length|] `appE` varE other)-                       )-                       []-            ]--    parseContents conKey contents errorFun =-        caseE (varE conKey)-              [ match wildP-                      ( guardedB $-                        [ do g <- normalG $ infixApp (varE conKey)-                                                     [|(==)|]-                                                     ([|T.pack|] `appE`-                                                        conNameExp opts con)-                             e <- parseArgs tName opts con contents-                             return (g, e)-                        | con <- cons-                        ]-                        ++-                        [ liftM2 (,)-                                 (normalG [e|otherwise|])-                                 ( varE errorFun-                                   `appE` (litE $ stringL $ show tName)-                                   `appE` listE (map ( litE-                                                     . stringL-                                                     . constructorTagModifier opts-                                                     . nameBase-                                                     . getConName-                                                     ) cons-                                                )-                                   `appE` ([|T.unpack|] `appE` varE conKey)-                                 )-                        ]-                      )-                      []-              ]--parseNullaryMatches :: Name -> Name -> [Q Match]-parseNullaryMatches tName conName =-    [ do arr <- newName "arr"-         match (conP 'Array [varP arr])-               (guardedB $-                [ liftM2 (,) (normalG $ [|V.null|] `appE` varE arr)-                             ([|pure|] `appE` conE conName)-                , liftM2 (,) (normalG [|otherwise|])-                             (parseTypeMismatch tName conName-                                (litE $ stringL "an empty Array")-                                (infixApp (litE $ stringL $ "Array of length ")-                                          [|(++)|]-                                          ([|show . V.length|] `appE` varE arr)-                                )-                             )-                ]-               )-               []-    , matchFailed tName conName "Array"-    ]--parseUnaryMatches :: Name -> [Q Match]-parseUnaryMatches conName =-    [ do arg <- newName "arg"-         match (varP arg)-               ( normalB $ infixApp (conE conName)-                                    [|(<$>)|]-                                    ([|parseJSON|] `appE` varE arg)-               )-               []-    ]--parseRecord :: Options -> Name -> Name -> [VarStrictType] -> Name -> ExpQ-parseRecord opts tName conName ts obj =-    foldl' (\a b -> infixApp a [|(<*>)|] b)-           (infixApp (conE conName) [|(<$>)|] x)-           xs-    where-      x:xs = [ [|lookupField|]-               `appE` (litE $ stringL $ show tName)-               `appE` (litE $ stringL $ constructorTagModifier opts $ nameBase conName)-               `appE` (varE obj)-               `appE` ( [|T.pack|] `appE` fieldLabelExp opts field-                      )-             | (field, _, _) <- ts-             ]--getValField :: Name -> String -> [MatchQ] -> Q Exp-getValField obj valFieldName matches = do-  val <- newName "val"-  doE [ bindS (varP val) $ infixApp (varE obj)-                                    [|(.:)|]-                                    ([|T.pack|] `appE`-                                       (litE $ stringL valFieldName))-      , noBindS $ caseE (varE val) matches-      ]---- | Generates code to parse the JSON encoding of a single constructor.-parseArgs :: Name -- ^ Name of the type to which the constructor belongs.-          -> Options -- ^ Encoding options.-          -> Con -- ^ Constructor for which to generate JSON parsing code.-          -> Either (String, Name) Name -- ^ Left (valFieldName, objName) or-                                        --   Right valName-          -> Q Exp--- Nullary constructors.-parseArgs tName _ (NormalC conName []) (Left (valFieldName, obj)) =-  getValField obj valFieldName $ parseNullaryMatches tName conName-parseArgs tName _ (NormalC conName []) (Right valName) =-  caseE (varE valName) $ parseNullaryMatches tName conName---- Unary constructors.-parseArgs _ _ (NormalC conName [_]) (Left (valFieldName, obj)) =-  getValField obj valFieldName $ parseUnaryMatches conName-parseArgs _ _ (NormalC conName [_]) (Right valName) =-  caseE (varE valName) $ parseUnaryMatches conName---- Polyadic constructors.-parseArgs tName _ (NormalC conName ts) (Left (valFieldName, obj)) =-    getValField obj valFieldName $ parseProduct tName conName $ genericLength ts-parseArgs tName _ (NormalC conName ts) (Right valName) =-    caseE (varE valName) $ parseProduct tName conName $ genericLength ts---- Records.-parseArgs tName opts (RecC conName ts) (Left (_, obj)) =-    parseRecord opts tName conName ts obj-parseArgs tName opts (RecC conName ts) (Right valName) = case (unwrapUnaryRecords opts,ts) of-  (True,[(_,st,ty)])-> parseArgs tName opts (NormalC conName [(st,ty)]) (Right valName)-  _ -> do-    obj <- newName "recObj"-    caseE (varE valName)-      [ match (conP 'Object [varP obj]) (normalB $ parseRecord opts tName conName ts obj) []-      , matchFailed tName conName "Object"-      ]---- Infix constructors. Apart from syntax these are the same as--- polyadic constructors.-parseArgs tName _ (InfixC _ conName _) (Left (valFieldName, obj)) =-    getValField obj valFieldName $ parseProduct tName conName 2-parseArgs tName _ (InfixC _ conName _) (Right valName) =-    caseE (varE valName) $ parseProduct tName conName 2---- Existentially quantified constructors. We ignore the quantifiers--- and proceed with the contained constructor.-parseArgs tName opts (ForallC _ _ con) contents =-    parseArgs tName opts con contents--#if MIN_VERSION_template_haskell(2,11,0)--- GADTs. We ignore the refined return type and proceed as if it were a--- NormalC or RecC.-parseArgs tName opts (GadtC conNames ts _) contents =-    parseArgs tName opts (NormalC (head conNames) ts) contents--parseArgs tName opts (RecGadtC conNames ts _) contents =-    parseArgs tName opts (RecC (head conNames) ts) contents-#endif---- | Generates code to parse the JSON encoding of an n-ary--- constructor.-parseProduct :: Name -- ^ Name of the type to which the constructor belongs.-             -> Name -- ^ 'Con'structor name.-             -> Integer -- ^ 'Con'structor arity.-             -> [Q Match]-parseProduct tName conName numArgs =-    [ do arr <- newName "arr"-         -- List of: "parseJSON (arr `V.unsafeIndex` <IX>)"-         let x:xs = [ [|parseJSON|]-                      `appE`-                      infixApp (varE arr)-                               [|V.unsafeIndex|]-                               (litE $ integerL ix)-                    | ix <- [0 .. numArgs - 1]-                    ]-         match (conP 'Array [varP arr])-               (normalB $ condE ( infixApp ([|V.length|] `appE` varE arr)-                                           [|(==)|]-                                           (litE $ integerL numArgs)-                                )-                                ( foldl' (\a b -> infixApp a [|(<*>)|] b)-                                         (infixApp (conE conName) [|(<$>)|] x)-                                         xs-                                )-                                ( parseTypeMismatch tName conName-                                    (litE $ stringL $ "Array of length " ++ show numArgs)-                                    ( infixApp (litE $ stringL $ "Array of length ")-                                               [|(++)|]-                                               ([|show . V.length|] `appE` varE arr)-                                    )-                                )-               )-               []-    , matchFailed tName conName "Array"-    ]-------------------------------------------------------------------------------------- Parsing errors-----------------------------------------------------------------------------------matchFailed :: Name -> Name -> String -> MatchQ-matchFailed tName conName expected = do-  other <- newName "other"-  match (varP other)-        ( normalB $ parseTypeMismatch tName conName-                      (litE $ stringL expected)-                      ([|valueConName|] `appE` varE other)-        )-        []--parseTypeMismatch :: Name -> Name -> ExpQ -> ExpQ -> ExpQ-parseTypeMismatch tName conName expected actual =-    foldl appE-          [|parseTypeMismatch'|]-          [ litE $ stringL $ nameBase conName-          , litE $ stringL $ show tName-          , expected-          , actual-          ]--class (FromJSON a) => LookupField a where-    lookupField :: String -> String -> Object -> T.Text -> Parser a--instance OVERLAPPABLE_ (FromJSON a) => LookupField a where-    lookupField tName rec obj key =-        case H.lookup key obj of-          Nothing -> unknownFieldFail tName rec (T.unpack key)-          Just v  -> parseJSON v--instance (FromJSON a) => LookupField (Maybe a) where-    lookupField _ _ = (.:?)--unknownFieldFail :: String -> String -> String -> Parser fail-unknownFieldFail tName rec key =-    fail $ printf "When parsing the record %s of type %s the key %s was not present."-                  rec tName key--noArrayFail :: String -> String -> Parser fail-noArrayFail t o = fail $ printf "When parsing %s expected Array but got %s." t o--noObjectFail :: String -> String -> Parser fail-noObjectFail t o = fail $ printf "When parsing %s expected Object but got %s." t o--firstElemNoStringFail :: String -> String -> Parser fail-firstElemNoStringFail t o = fail $ printf "When parsing %s expected an Array of 2 elements where the first element is a String but got %s at the first element." t o--wrongPairCountFail :: String -> String -> Parser fail-wrongPairCountFail t n =-    fail $ printf "When parsing %s expected an Object with a single tag/contents pair but got %s pairs."-                  t n--noStringFail :: String -> String -> Parser fail-noStringFail t o = fail $ printf "When parsing %s expected String but got %s." t o--noMatchFail :: String -> String -> Parser fail-noMatchFail t o =-    fail $ printf "When parsing %s expected a String with the tag of a constructor but got %s." t o--not2ElemArray :: String -> Int -> Parser fail-not2ElemArray t i = fail $ printf "When parsing %s expected an Array of 2 elements but got %i elements" t i--conNotFoundFail2ElemArray :: String -> [String] -> String -> Parser fail-conNotFoundFail2ElemArray t cs o =-    fail $ printf "When parsing %s expected a 2-element Array with a tag and contents element where the tag is one of [%s], but got %s."-                  t (intercalate ", " cs) o--conNotFoundFailObjectSingleField :: String -> [String] -> String -> Parser fail-conNotFoundFailObjectSingleField t cs o =-    fail $ printf "When parsing %s expected an Object with a single tag/contents pair where the tag is one of [%s], but got %s."-                  t (intercalate ", " cs) o--conNotFoundFailTaggedObject :: String -> [String] -> String -> Parser fail-conNotFoundFailTaggedObject t cs o =-    fail $ printf "When parsing %s expected an Object with a tag field where the value is one of [%s], but got %s."-                  t (intercalate ", " cs) o--parseTypeMismatch' :: String -> String -> String -> String -> Parser fail-parseTypeMismatch' conName tName expected actual =-    fail $ printf "When parsing the constructor %s of type %s expected %s but got %s."-                  conName tName expected actual-------------------------------------------------------------------------------------- Utility functions------------------------------------------------------------------------------------- | Boilerplate for top level splices.------ The given 'Name' must meet one of two criteria:------ 1. It must be the name of a type constructor of a plain data type or newtype.--- 2. It must be the name of a data family instance or newtype instance constructor.---- Any other value will result in an exception.-withType :: Name-         -> (Name -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q a)-         -- ^ Function that generates the actual code. Will be applied-         -- to the datatype/data family 'Name', type variable binders and-         -- constructors extracted from the given 'Name'. If the 'Name' is-         -- from a data family instance constructor, it will also have its-         -- instantiated types; otherwise, it will be 'Nothing'.-         -> Q a-         -- ^ Resulting value in the 'Q'uasi monad.-withType name f = do-    info <- reify name-    case info of-      TyConI dec ->-        case dec of-#if MIN_VERSION_template_haskell(2,11,0)-          DataD    _ _ tvbs _ cons _ -> f name tvbs cons Nothing-          NewtypeD _ _ tvbs _ con  _ -> f name tvbs [con] Nothing-#else-          DataD    _ _ tvbs   cons _ -> f name tvbs cons Nothing-          NewtypeD _ _ tvbs   con  _ -> f name tvbs [con] Nothing-#endif-          other -> error $ ns ++ "Unsupported type: " ++ show other-#if MIN_VERSION_template_haskell(2,11,0)-      DataConI _ _ parentName   -> do-#else-      DataConI _ _ parentName _ -> do-#endif-        parentInfo <- reify parentName-        case parentInfo of-#if MIN_VERSION_template_haskell(2,11,0)-          FamilyI (DataFamilyD _ tvbs _) decs ->-#else-          FamilyI (FamilyD DataFam _ tvbs _) decs ->-#endif-            let instDec = flip find decs $ \dec -> case dec of-#if MIN_VERSION_template_haskell(2,11,0)-                  DataInstD    _ _ _ _ cons _ -> any ((name ==) . getConName) cons-                  NewtypeInstD _ _ _ _ con  _ -> name == getConName con-#else-                  DataInstD    _ _ _   cons _ -> any ((name ==) . getConName) cons-                  NewtypeInstD _ _ _   con  _ -> name == getConName con-#endif-                  _ -> error $ ns ++ "Must be a data or newtype instance."-             in case instDec of-#if MIN_VERSION_template_haskell(2,11,0)-                  Just (DataInstD    _ _ instTys _ cons _) -> f parentName tvbs cons $ Just instTys-                  Just (NewtypeInstD _ _ instTys _ con  _) -> f parentName tvbs [con] $ Just instTys-#else-                  Just (DataInstD    _ _ instTys   cons _) -> f parentName tvbs cons $ Just instTys-                  Just (NewtypeInstD _ _ instTys   con  _) -> f parentName tvbs [con] $ Just instTys-#endif-                  _ -> error $ ns ++-                    "Could not find data or newtype instance constructor."-          _ -> error $ ns ++ "Data constructor " ++ show name ++-            " is not from a data family instance constructor."-#if MIN_VERSION_template_haskell(2,11,0)-      FamilyI DataFamilyD{} _ ->-#else-      FamilyI (FamilyD DataFam _ _ _) _ ->-#endif-        error $ ns ++-          "Cannot use a data family name. Use a data family instance constructor instead."-      _ -> error $ ns ++ "I need the name of a plain data type constructor, "-                      ++ "or a data family instance constructor."-  where-    ns :: String-    ns = "Data.Aeson.TH.withType: "---- | Infer the context and instance head needed for a FromJSON or ToJSON instance.-buildTypeInstance :: Name-                  -- ^ The type constructor or data family name-                  -> Name-                  -- ^ The typeclass name ('ToJSON' or 'FromJSON')-                  -> [TyVarBndr]-                  -- ^ The type variables from the data type/data family declaration-                  -> Maybe [Type]-                  -- ^ 'Just' the types used to instantiate a data family instance,-                  -- or 'Nothing' if it's a plain data type-                  -> Q (Cxt, Type)-                  -- ^ The resulting 'Cxt' and 'Type' to use in a class instance--- Plain data type/newtype case-buildTypeInstance tyConName constraint tvbs Nothing =-    let varTys :: [Type]-        varTys = map tvbToType tvbs-    in buildTypeInstanceFromTys tyConName constraint varTys False--- Data family instance case------ The CPP is present to work around a couple of annoying old GHC bugs.--- See Note [Polykinded data families in Template Haskell]-buildTypeInstance dataFamName constraint tvbs (Just instTysAndKinds) = do-#if !(MIN_VERSION_template_haskell(2,8,0)) || MIN_VERSION_template_haskell(2,10,0)-    let instTys :: [Type]-        instTys = zipWith stealKindForType tvbs instTysAndKinds-#else-    let kindVarNames :: [Name]-        kindVarNames = nub $ concatMap (tyVarNamesOfType . tvbKind) tvbs--        -- Gets all of the type/kind variable names mentioned somewhere in a Type.-        tyVarNamesOfType :: Type -> [Name]-        tyVarNamesOfType = go-          where-            go :: Type -> [Name]-            go (AppT t1 t2) = go t1 ++ go t2-            go (SigT t k)   = go t  ++ go k-            go (VarT n)     = [n]-            go _            = []--        numKindVars :: Int-        numKindVars = length kindVarNames--        givenKinds, givenKinds' :: [Kind]-        givenTys                :: [Type]-        (givenKinds, givenTys) = splitAt numKindVars instTysAndKinds-        givenKinds' = map sanitizeStars givenKinds--        -- A GHC 7.6-specific bug requires us to replace all occurrences of-        -- (ConT GHC.Prim.*) with StarT, or else Template Haskell will reject it.-        -- Luckily, (ConT GHC.Prim.*) only seems to occur in this one spot.-        sanitizeStars :: Kind -> Kind-        sanitizeStars = go-          where-            go :: Kind -> Kind-            go (AppT t1 t2)                 = AppT (go t1) (go t2)-            go (SigT t k)                   = SigT (go t) (go k)-            go (ConT n) | n == starKindName = StarT-            go t                            = t--            -- It's quite awkward to import * from GHC.Prim, so we'll just-            -- hack our way around it.-            starKindName :: Name-            starKindName = mkNameG_tc "ghc-prim" "GHC.Prim" "*"--        -- Generate a list of fresh names with a common prefix, and numbered suffixes.-        newNameList :: String -> Int -> Q [Name]-        newNameList prefix n = mapM (newName . (prefix ++) . show) [1..n]--    -- If we run this code with GHC 7.8, we might have to generate extra type-    -- variables to compensate for any type variables that Template Haskell-    -- eta-reduced away.-    -- See Note [Polykinded data families in Template Haskell]-    xTypeNames <- newNameList "tExtra" (length tvbs - length givenTys)--    let xTys   :: [Type]-        xTys = map VarT xTypeNames-        -- ^ Because these type variables were eta-reduced away, we can only-        --   determine their kind by using stealKindForType. Therefore, we mark-        --   them as VarT to ensure they will be given an explicit kind annotation-        --   (and so the kind inference machinery has the right information).--        substNameWithKind :: Name -> Kind -> Type -> Type-        substNameWithKind n k = substType (M.singleton n k)--        substNamesWithKinds :: [(Name, Kind)] -> Type -> Type-        substNamesWithKinds nks t = foldr' (uncurry substNameWithKind) t nks--        -- The types from the data family instance might not have explicit kind-        -- annotations, which the kind machinery needs to work correctly. To-        -- compensate, we use stealKindForType to explicitly annotate any-        -- types without kind annotations.-        instTys :: [Type]-        instTys = map (substNamesWithKinds (zip kindVarNames givenKinds'))-                  -- Note that due to a GHC 7.8-specific bug-                  -- (see Note [Polykinded data families in Template Haskell]),-                  -- there may be more kind variable names than there are kinds-                  -- to substitute. But this is OK! If a kind is eta-reduced, it-                  -- means that is was not instantiated to something more specific,-                  -- so we need not substitute it. Using stealKindForType will-                  -- grab the correct kind.-                $ zipWith stealKindForType tvbs (givenTys ++ xTys)-#endif-    buildTypeInstanceFromTys dataFamName constraint instTys True---- For the given Types, generate an instance context and head.-buildTypeInstanceFromTys :: Name-                         -- ^ The type constructor or data family name-                         -> Name-                         -- ^ The typeclass name ('ToJSON' or 'FromJSON')-                         -> [Type]-                         -- ^ The types to instantiate the instance with-                         -> Bool-                         -- ^ True if it's a data family, False otherwise-                         -> Q (Cxt, Type)-buildTypeInstanceFromTys tyConName constraint varTysOrig isDataFamily = do-    -- Make sure to expand through type/kind synonyms! Otherwise, we won't-    -- be able to infer constraints as accurately.-    varTysExp <- mapM expandSyn varTysOrig--    let preds    :: [Maybe Pred]-        -- Derive instance constraints for type variables of kind *-        preds = map (deriveConstraint constraint) varTysExp--        varTys :: [Type]-        -- See Note [Kind signatures in derived instances] for an explanation-        -- of the isDataFamily check.-        varTys =-          if isDataFamily-             then varTysOrig-             else map unSigT varTysOrig--        instanceCxt :: Cxt-        instanceCxt = catMaybes preds--        instanceType :: Type-        instanceType = AppT (ConT constraint)-                     $ applyTyCon tyConName varTys--    return (instanceCxt, instanceType)---- | Attempt to derive a constraint on a Type. If it's of kind *,--- we give it Just a ToJSON/FromJSON constraint. Otherwise, return Nothing.-deriveConstraint :: Name -> Type -> Maybe Pred-deriveConstraint constraint t-  | isTyVar t && hasKindStar t = Just $ applyCon constraint $ varTToName t-  | otherwise                  = Nothing--{--Note [Polykinded data families in Template Haskell]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--In order to come up with the correct instance context and head for an instance, e.g.,--  instance C a => C (Data a) where ...--We need to know the exact types and kinds used to instantiate the instance. For-plain old datatypes, this is simple: every type must be a type variable, and-Template Haskell reliably tells us the type variables and their kinds.--Doing the same for data families proves to be much harder for three reasons:--1. On any version of Template Haskell, it may not tell you what an instantiated-   type's kind is. For instance, in the following data family instance:--     data family Fam (f :: * -> *) (a :: *)-     data instance Fam f a--   Then if we use TH's reify function, it would tell us the TyVarBndrs of the-   data family declaration are:--     [KindedTV f (AppT (AppT ArrowT StarT) StarT),KindedTV a StarT]--   and the instantiated types of the data family instance are:--     [VarT f1,VarT a1]--   We can't just pass [VarT f1,VarT a1] to buildTypeInstanceFromTys, since we-   have no way of knowing their kinds. Luckily, the TyVarBndrs tell us what the-   kind is in case an instantiated type isn't a SigT, so we use the stealKindForType-   function to ensure all of the instantiated types are SigTs before passing them-   to buildTypeInstanceFromTys.-2. On GHC 7.6 and 7.8, a bug is present in which Template Haskell lists all of-   the specified kinds of a data family instance efore any of the instantiated-   types. Fortunately, this is easy to deal with: you simply count the number of-   distinct kind variables in the data family declaration, take that many elements-   from the front of the  Types list of the data family instance, substitute the-   kind variables with their respective instantiated kinds (which you took earlier),-   and proceed as normal.-3. On GHC 7.8, an even uglier bug is present (GHC Trac #9692) in which Template-   Haskell might not even list all of the Types of a data family instance, since-   they are eta-reduced away! And yes, kinds can be eta-reduced too.--   The simplest workaround is to count how many instantiated types are missing from-   the list and generate extra type variables to use in their place. Luckily, we-   needn't worry much if its kind was eta-reduced away, since using stealKindForType-   will get it back.--Note [Kind signatures in derived instances]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--It is possible to put explicit kind signatures into the derived instances, e.g.,--  instance C a => C (Data (f :: * -> *)) where ...--But it is preferable to avoid this if possible. If we come up with an incorrect-kind signature (which is entirely possible, since Template Haskell doesn't always-have the best track record with reifying kind signatures), then GHC will flat-out-reject the instance, which is quite unfortunate.--Plain old datatypes have the advantage that you can avoid using any kind signatures-at all in their instances. This is because a datatype declaration uses all type-variables, so the types that we use in a derived instance uniquely determine their-kinds. As long as we plug in the right types, the kind inferencer can do the rest-of the work. For this reason, we use unSigT to remove all kind signatures before-splicing in the instance context and head.--Data family instances are trickier, since a data family can have two instances that-are distinguished by kind alone, e.g.,--  data family Fam (a :: k)-  data instance Fam (a :: * -> *)-  data instance Fam (a :: *)--If we dropped the kind signatures for C (Fam a), then GHC will have no way of-knowing which instance we are talking about. To avoid this scenario, we always-include explicit kind signatures in data family instances. There is a chance that-the inferred kind signatures will be incorrect, but if so, we can always fall back-on the mk- functions.--}---- | If a VarT is missing an explicit kind signature, steal it from a TyVarBndr.-stealKindForType :: TyVarBndr -> Type -> Type-stealKindForType tvb t@VarT{} = SigT t (tvbKind tvb)-stealKindForType _   t        = t---- | Extracts the kind from a type variable binder.-tvbKind :: TyVarBndr -> Kind-#if MIN_VERSION_template_haskell(2,8,0)-tvbKind (PlainTV  _  ) = StarT-#else-tvbKind (PlainTV  _  ) = StarK-#endif-tvbKind (KindedTV _ k) = k--tvbToType :: TyVarBndr -> Type-tvbToType (PlainTV n)    = VarT n-tvbToType (KindedTV n k) = SigT (VarT n) k---- | Returns True if a Type has kind *.-hasKindStar :: Type -> Bool-hasKindStar VarT{}         = True-#if MIN_VERSION_template_haskell(2,8,0)-hasKindStar (SigT _ StarT) = True-#else-hasKindStar (SigT _ StarK) = True-#endif-hasKindStar _              = False---- | Extract the Name from a type variable. If the argument Type is not a--- type variable, throw an error.-varTToName :: Type -> Name-varTToName (VarT n)   = n-varTToName (SigT t _) = varTToName t-varTToName _          = error "Not a type variable!"---- | Extracts the name from a constructor.-getConName :: Con -> Name-getConName (NormalC name _)  = name-getConName (RecC name _)     = name-getConName (InfixC _ name _) = name-getConName (ForallC _ _ con) = getConName con-#if MIN_VERSION_template_haskell(2,11,0)-getConName (GadtC    names _ _) = head names-getConName (RecGadtC names _ _) = head names-#endif---- | Fully applies a type constructor to its type variables.-applyTyCon :: Name -> [Type] -> Type-applyTyCon = foldl' AppT . ConT---- | Is the given type a variable?-isTyVar :: Type -> Bool-isTyVar (VarT _)   = True-isTyVar (SigT t _) = isTyVar t-isTyVar _          = False---- | Peel off a kind signature from a Type (if it has one).-unSigT :: Type -> Type-unSigT (SigT t _) = t-unSigT t          = t---- | Makes a string literal expression from a constructor's name.-conNameExp :: Options -> Con -> Q Exp-conNameExp opts = litE-                . stringL-                . constructorTagModifier opts-                . nameBase-                . getConName---- | Creates a string literal expression from a record field label.-fieldLabelExp :: Options -- ^ Encoding options-              -> Name-              -> Q Exp-fieldLabelExp opts = litE . stringL . fieldLabelModifier opts . nameBase---- | The name of the outermost 'Value' constructor.-valueConName :: Value -> String-valueConName (Object _) = "Object"-valueConName (Array  _) = "Array"-valueConName (String _) = "String"-valueConName (Number _) = "Number"-valueConName (Bool   _) = "Boolean"-valueConName Null       = "Null"--applyCon :: Name -> Name -> Pred-applyCon con t =-#if MIN_VERSION_template_haskell(2,10,0)-          AppT (ConT con) (VarT t)-#else-          ClassP con [VarT t]-#endif------------------------------------------------------------------------------------ Expanding type synonyms------------------------------------------------------------------------------------ | Expands all type synonyms in a type. Written by Dan Rosén in the--- @genifunctors@ package (licensed under BSD3).-expandSyn :: Type -> Q Type-expandSyn (ForallT tvs ctx t) = fmap (ForallT tvs ctx) $ expandSyn t-expandSyn t@AppT{}            = expandSynApp t []-expandSyn t@ConT{}            = expandSynApp t []-expandSyn (SigT t k)          = do t' <- expandSyn t-                                   k' <- expandSynKind k-                                   return (SigT t' k')-expandSyn t                   = return t--expandSynKind :: Kind -> Q Kind-#if MIN_VERSION_template_haskell(2,8,0)-expandSynKind = expandSyn-#else-expandSynKind = return -- There are no kind synonyms to deal with-#endif--expandSynApp :: Type -> [Type] -> Q Type-expandSynApp (AppT t1 t2) ts = do-    t2' <- expandSyn t2-    expandSynApp t1 (t2':ts)-expandSynApp (ConT n) ts | nameBase n == "[]" = return $ foldl' AppT ListT ts-expandSynApp t@(ConT n) ts = do-    info <- reify n-    case info of-        TyConI (TySynD _ tvs rhs) ->-            let (ts', ts'') = splitAt (length tvs) ts-                subs = mkSubst tvs ts'-                rhs' = substType subs rhs-             in expandSynApp rhs' ts''-        _ -> return $ foldl' AppT t ts-expandSynApp t ts = do-    t' <- expandSyn t-    return $ foldl' AppT t' ts--type TypeSubst = Map Name Type--mkSubst :: [TyVarBndr] -> [Type] -> TypeSubst-mkSubst vs ts =-   let vs' = map un vs-       un (PlainTV v)    = v-       un (KindedTV v _) = v-   in M.fromList $ zip vs' ts--substType :: TypeSubst -> Type -> Type-substType subs (ForallT v c t) = ForallT v c $ substType subs t-substType subs t@(VarT n)      = M.findWithDefault t n subs-substType subs (AppT t1 t2)    = AppT (substType subs t1) (substType subs t2)-substType subs (SigT t k)      = SigT (substType subs t)-#if MIN_VERSION_template_haskell(2,8,0)-                                      (substType subs k)-#else-                                      k-#endif-substType _ t                  = t+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE UndecidableInstances #-}+#if __GLASGOW_HASKELL__ >= 800+-- a) THQ works on cross-compilers and unregisterised GHCs+-- b) may make compilation faster as no dynamic loading is ever needed (not sure about this)+-- c) removes one hindrance to have code inferred as SafeHaskell safe+{-# LANGUAGE TemplateHaskellQuotes #-}+#else+{-# LANGUAGE TemplateHaskell #-}+#endif++#include "overlapping-compat.h"++{-|+Module:      Data.Aeson.TH+Copyright:   (c) 2011-2016 Bryan O'Sullivan+             (c) 2011 MailRank, Inc.+License:     BSD3+Stability:   experimental+Portability: portable++Functions to mechanically derive 'ToJSON' and 'FromJSON' instances. Note that+you need to enable the @TemplateHaskell@ language extension in order to use this+module.++An example shows how instances are generated for arbitrary data types. First we+define a data type:++@+data D a = Nullary+         | Unary Int+         | Product String Char a+         | Record { testOne   :: Double+                  , testTwo   :: Bool+                  , testThree :: D a+                  } deriving Eq+@++Next we derive the necessary instances. Note that we make use of the+feature to change record field names. In this case we drop the first 4+characters of every field name. We also modify constructor names by+lower-casing them:++@+$('deriveJSON' 'defaultOptions'{'fieldLabelModifier' = 'drop' 4, 'constructorTagModifier' = map toLower} ''D)+@++Now we can use the newly created instances.++@+d :: D 'Int'+d = Record { testOne = 3.14159+           , testTwo = 'True'+           , testThree = Product \"test\" \'A\' 123+           }+@++>>> fromJSON (toJSON d) == Success d+> True++This also works for data family instances, but instead of passing in the data+family name (with double quotes), we pass in a data family instance+constructor (with a single quote):++@+data family DF a+data instance DF Int = DF1 Int+                     | DF2 Int Int+                     deriving Eq++$('deriveJSON' 'defaultOptions' 'DF1)+-- Alternatively, one could pass 'DF2 instead+@++Please note that you can derive instances for tuples using the following syntax:++@+-- FromJSON and ToJSON instances for 4-tuples.+$('deriveJSON' 'defaultOptions' ''(,,,))+@++-}++module Data.Aeson.TH+    (+      -- * Encoding configuration+      Options(..)+    , SumEncoding(..)+    , defaultOptions+    , defaultTaggedObject++     -- * FromJSON and ToJSON derivation+    , deriveJSON+    , deriveJSON1+    , deriveJSON2++    , deriveToJSON+    , deriveToJSON1+    , deriveToJSON2+    , deriveFromJSON+    , deriveFromJSON1+    , deriveFromJSON2++    , mkToJSON+    , mkLiftToJSON+    , mkLiftToJSON2+    , mkToEncoding+    , mkLiftToEncoding+    , mkLiftToEncoding2+    , mkParseJSON+    , mkLiftParseJSON+    , mkLiftParseJSON2+    ) where++import Prelude ()+import Prelude.Compat hiding (exp)++import Control.Applicative ((<|>))+import Data.Aeson (Object, (.=), (.:), FromJSON(..), FromJSON1(..), FromJSON2(..), ToJSON(..), ToJSON1(..), ToJSON2(..))+import Data.Aeson.Types (Options(..), Parser, SumEncoding(..), Value(..), defaultOptions, defaultTaggedObject)+import Data.Aeson.Types.Internal ((<?>), Pair, JSONPathElement(Key))+import Data.Aeson.Types.FromJSON (parseOptionalFieldWith)+import Control.Monad (liftM2, unless, when)+import Data.Foldable (foldr')+#if MIN_VERSION_template_haskell(2,8,0) && !MIN_VERSION_template_haskell(2,10,0)+import Data.List (nub)+#endif+import Data.List (find, foldl', genericLength , intercalate , intersperse, partition, union)+import Data.List.NonEmpty ((<|), NonEmpty((:|)))+import Data.Map (Map)+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)+import Data.Set (Set)+#if MIN_VERSION_template_haskell(2,8,0)+import Language.Haskell.TH hiding (Arity)+#else+import Language.Haskell.TH+#endif+import Language.Haskell.TH.Syntax (VarStrictType)+#if MIN_VERSION_template_haskell(2,7,0) && !(MIN_VERSION_template_haskell(2,8,0))+import Language.Haskell.TH.Lib (starK)+#endif+#if MIN_VERSION_template_haskell(2,8,0) && !(MIN_VERSION_template_haskell(2,10,0))+import Language.Haskell.TH.Syntax (mkNameG_tc)+#endif+import Text.Printf (printf)+import qualified Data.Aeson as A+import qualified Data.Aeson.Encoding.Internal as E+import qualified Data.Foldable as F (all)+import qualified Data.HashMap.Strict as H (lookup, toList)+import qualified Data.List.NonEmpty as NE (drop, length, reverse, splitAt)+import qualified Data.Map as M (fromList, findWithDefault, keys, lookup , singleton, size)+import qualified Data.Set as Set (empty, insert, member)+import qualified Data.Text as T (Text, pack, unpack)+import qualified Data.Vector as V (unsafeIndex, null, length, create, fromList)+import qualified Data.Vector.Mutable as VM (unsafeNew, unsafeWrite)+++--------------------------------------------------------------------------------+-- Convenience+--------------------------------------------------------------------------------++-- | Generates both 'ToJSON' and 'FromJSON' instance declarations for the given+-- data type or data family instance constructor.+--+-- This is a convienience function which is equivalent to calling both+-- 'deriveToJSON' and 'deriveFromJSON'.+deriveJSON :: Options+           -- ^ Encoding options.+           -> Name+           -- ^ Name of the type for which to generate 'ToJSON' and 'FromJSON'+           -- instances.+           -> Q [Dec]+deriveJSON = deriveJSONBoth deriveToJSON deriveFromJSON++-- | Generates both 'ToJSON1' and 'FromJSON1' instance declarations for the given+-- data type or data family instance constructor.+--+-- This is a convienience function which is equivalent to calling both+-- 'deriveToJSON1' and 'deriveFromJSON1'.+deriveJSON1 :: Options+            -- ^ Encoding options.+            -> Name+            -- ^ Name of the type for which to generate 'ToJSON1' and 'FromJSON1'+            -- instances.+            -> Q [Dec]+deriveJSON1 = deriveJSONBoth deriveToJSON1 deriveFromJSON1++-- | Generates both 'ToJSON2' and 'FromJSON2' instance declarations for the given+-- data type or data family instance constructor.+--+-- This is a convienience function which is equivalent to calling both+-- 'deriveToJSON2' and 'deriveFromJSON2'.+deriveJSON2 :: Options+            -- ^ Encoding options.+            -> Name+            -- ^ Name of the type for which to generate 'ToJSON2' and 'FromJSON2'+            -- instances.+            -> Q [Dec]+deriveJSON2 = deriveJSONBoth deriveToJSON2 deriveFromJSON2++--------------------------------------------------------------------------------+-- ToJSON+--------------------------------------------------------------------------------++{-+TODO: Don't constrain phantom type variables.++data Foo a = Foo Int+instance (ToJSON a) ⇒ ToJSON Foo where ...++The above (ToJSON a) constraint is not necessary and perhaps undesirable.+-}++-- | Generates a 'ToJSON' instance declaration for the given data type or+-- data family instance constructor.+deriveToJSON :: Options+             -- ^ Encoding options.+             -> Name+             -- ^ Name of the type for which to generate a 'ToJSON' instance+             -- declaration.+             -> Q [Dec]+deriveToJSON = deriveToJSONCommon toJSONClass++-- | Generates a 'ToJSON1' instance declaration for the given data type or+-- data family instance constructor.+deriveToJSON1 :: Options+              -- ^ Encoding options.+              -> Name+              -- ^ Name of the type for which to generate a 'ToJSON1' instance+              -- declaration.+              -> Q [Dec]+deriveToJSON1 = deriveToJSONCommon toJSON1Class++-- | Generates a 'ToJSON2' instance declaration for the given data type or+-- data family instance constructor.+deriveToJSON2 :: Options+              -- ^ Encoding options.+              -> Name+              -- ^ Name of the type for which to generate a 'ToJSON2' instance+              -- declaration.+              -> Q [Dec]+deriveToJSON2 = deriveToJSONCommon toJSON2Class++deriveToJSONCommon :: JSONClass+                   -- ^ The ToJSON variant being derived.+                   -> Options+                   -- ^ Encoding options.+                   -> Name+                   -- ^ Name of the type for which to generate an instance.+                   -> Q [Dec]+deriveToJSONCommon = deriveJSONClass [ (ToJSON,     \jc _ -> consToValue    jc)+                                     , (ToEncoding, \jc _ -> consToEncoding jc)+                                     ]++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a 'Value'.+mkToJSON :: Options -- ^ Encoding options.+         -> Name -- ^ Name of the type to encode.+         -> Q Exp+mkToJSON = mkToJSONCommon toJSONClass++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a 'Value' by using the given encoding+-- function on occurrences of the last type parameter.+mkLiftToJSON :: Options -- ^ Encoding options.+             -> Name -- ^ Name of the type to encode.+             -> Q Exp+mkLiftToJSON = mkToJSONCommon toJSON1Class++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a 'Value' by using the given encoding+-- functions on occurrences of the last two type parameters.+mkLiftToJSON2 :: Options -- ^ Encoding options.+              -> Name -- ^ Name of the type to encode.+              -> Q Exp+mkLiftToJSON2 = mkToJSONCommon toJSON2Class++mkToJSONCommon :: JSONClass -- ^ Which class's method is being derived.+               -> Options -- ^ Encoding options.+               -> Name -- ^ Name of the encoded type.+               -> Q Exp+mkToJSONCommon = mkFunCommon (\jc _ -> consToValue jc)++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a JSON string.+mkToEncoding :: Options -- ^ Encoding options.+             -> Name -- ^ Name of the type to encode.+             -> Q Exp+mkToEncoding = mkToEncodingCommon toJSONClass++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a JSON string by using the given encoding+-- function on occurrences of the last type parameter.+mkLiftToEncoding :: Options -- ^ Encoding options.+                 -> Name -- ^ Name of the type to encode.+                 -> Q Exp+mkLiftToEncoding = mkToEncodingCommon toJSON1Class++-- | Generates a lambda expression which encodes the given data type or+-- data family instance constructor as a JSON string by using the given encoding+-- functions on occurrences of the last two type parameters.+mkLiftToEncoding2 :: Options -- ^ Encoding options.+                  -> Name -- ^ Name of the type to encode.+                  -> Q Exp+mkLiftToEncoding2 = mkToEncodingCommon toJSON2Class++mkToEncodingCommon :: JSONClass -- ^ Which class's method is being derived.+                   -> Options -- ^ Encoding options.+                   -> Name -- ^ Name of the encoded type.+                   -> Q Exp+mkToEncodingCommon = mkFunCommon (\jc _ -> consToEncoding jc)++-- | Helper function used by both 'deriveToJSON' and 'mkToJSON'. Generates+-- code to generate a 'Value' of a number of constructors. All constructors+-- must be from the same type.+consToValue :: JSONClass+            -- ^ The ToJSON variant being derived.+            -> Options+            -- ^ Encoding options.+            -> [Con]+            -- ^ Constructors for which to generate JSON generating code.+            -> Q Exp++consToValue _ _ [] = error $ "Data.Aeson.TH.consToValue: "+                            ++ "Not a single constructor given!"++consToValue jc opts cons = do+    value <- newName "value"+    tjs   <- newNameList "_tj"  $ arityInt jc+    tjls  <- newNameList "_tjl" $ arityInt jc+    let zippedTJs      = zip tjs tjls+        interleavedTJs = interleave tjs tjls+    lamE (map varP $ interleavedTJs ++ [value]) $+        caseE (varE value) (matches zippedTJs)+  where+    matches tjs = case cons of+      -- A single constructor is directly encoded. The constructor itself may be+      -- forgotten.+      [con] -> [argsToValue jc tjs opts False con]+      _ | allNullaryToStringTag opts && all isNullary cons ->+              [ match (conP conName []) (normalB $ conStr opts conName) []+              | con <- cons+              , let conName = getConName con+              ]+        | otherwise -> [argsToValue jc tjs opts True con | con <- cons]++conStr :: Options -> Name -> Q Exp+conStr opts = appE [|String|] . conTxt opts++conTxt :: Options -> Name -> Q Exp+conTxt opts = appE [|T.pack|] . conStringE opts++conStringE :: Options -> Name -> Q Exp+conStringE opts = stringE . constructorTagModifier opts . nameBase++-- | Helper function used by both 'deriveToJSON' and 'mkToEncoding'. Generates+-- code to write out a value for a number of constructors. All constructors+-- must be from the same type.+consToEncoding :: JSONClass+               -- ^ The ToJSON variant being derived.+               -> Options+               -- ^ Encoding options.+               -> [Con]+               -- ^ Constructors for which to generate JSON generating code.+               -> Q Exp++consToEncoding _ _ [] = error $ "Data.Aeson.TH.consToEncoding: "+                        ++ "Not a single constructor given!"++consToEncoding jc opts cons = do+    value <- newName "value"+    tes   <- newNameList "_te"  $ arityInt jc+    tels  <- newNameList "_tel" $ arityInt jc+    let zippedTEs      = zip tes tels+        interleavedTEs = interleave tes tels+    lamE (map varP $ interleavedTEs ++ [value]) $+        caseE (varE value) (matches zippedTEs)+  where+    matches tes = case cons of+      -- A single constructor is directly encoded. The constructor itself may be+      -- forgotten.+      [con] -> [argsToEncoding jc tes opts False con]+      -- Encode just the name of the constructor of a sum type iff all the+      -- constructors are nullary.+      _ | allNullaryToStringTag opts && all isNullary cons ->+              [ match (conP conName [])+                (normalB $ encStr opts conName) []+              | con <- cons+              , let conName = getConName con+              ]+        | otherwise -> [argsToEncoding jc tes opts True con | con <- cons]++encStr :: Options -> Name -> Q Exp+encStr opts = appE [|E.text|] . conTxt opts++-- | If constructor is nullary.+isNullary :: Con -> Bool+isNullary (NormalC _ []) = True+isNullary _ = False++sumToValue :: Options -> Bool -> Name -> Q Exp -> Q Exp+sumToValue opts multiCons conName exp+    | multiCons =+        case sumEncoding opts of+          TwoElemArray ->+              [|Array|] `appE` ([|V.fromList|] `appE` listE [conStr opts conName, exp])+          TaggedObject{tagFieldName, contentsFieldName} ->+              [|A.object|] `appE` listE+                [ infixApp [|T.pack tagFieldName|]     [|(.=)|] (conStr opts conName)+                , infixApp [|T.pack contentsFieldName|] [|(.=)|] exp+                ]+          ObjectWithSingleField ->+              [|A.object|] `appE` listE+                [ infixApp (conTxt opts conName) [|(.=)|] exp+                ]+          UntaggedValue -> exp+    | otherwise = exp++nullarySumToValue :: Options -> Bool -> Name -> Q Exp+nullarySumToValue opts multiCons conName =+    case sumEncoding opts of+      TaggedObject{tagFieldName} ->+          [|A.object|] `appE` listE+            [ infixApp [|T.pack tagFieldName|] [|(.=)|] (conStr opts conName)+            ]+      UntaggedValue -> conStr opts conName+      _ -> sumToValue opts multiCons conName [e|toJSON ([] :: [()])|]++-- | Generates code to generate the JSON encoding of a single constructor.+argsToValue :: JSONClass -> [(Name, Name)] -> Options -> Bool -> Con -> Q Match+-- Nullary constructors. Generates code that explicitly matches against the+-- constructor even though it doesn't contain data. This is useful to prevent+-- type errors.+argsToValue jc tjs opts multiCons (NormalC conName []) = do+    ([], _) <- reifyConTys jc tjs conName+    match (conP conName [])+          (normalB (nullarySumToValue opts multiCons conName))+          []++-- Polyadic constructors with special case for unary constructors.+argsToValue jc tjs opts multiCons (NormalC conName ts) = do+    (argTys, tvMap) <- reifyConTys jc tjs conName+    let len = length ts+    args <- newNameList "arg" len+    js <- case [ dispatchToJSON jc conName tvMap argTy+                   `appE` varE arg+               | (arg, argTy) <- zip args argTys+               ] of+            -- Single argument is directly converted.+            [e] -> return e+            -- Multiple arguments are converted to a JSON array.+            es  -> do+              mv <- newName "mv"+              let newMV = bindS (varP mv)+                                ([|VM.unsafeNew|] `appE`+                                  litE (integerL $ fromIntegral len))+                  stmts = [ noBindS $+                              [|VM.unsafeWrite|] `appE`+                                varE mv `appE`+                                  litE (integerL ix) `appE`+                                    e+                          | (ix, e) <- zip [(0::Integer)..] es+                          ]+                  ret = noBindS $ [|return|] `appE` varE mv+              return $ [|Array|] `appE`+                         (varE 'V.create `appE`+                           doE (newMV:stmts++[ret]))+    match (conP conName $ map varP args)+          (normalB $ sumToValue opts multiCons conName js)+          []++-- Records.+argsToValue jc tjs opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of+  (True,True,[(_,st,ty)]) -> argsToValue jc tjs opts multiCons (NormalC conName [(st,ty)])+  _ -> do+    (argTys, tvMap) <- reifyConTys jc tjs conName+    args <- newNameList "arg" $ length ts+    let exp = [|A.object|] `appE` pairs++        pairs | omitNothingFields opts = infixApp maybeFields+                                                  [|(++)|]+                                                  restFields+              | otherwise = listE $ map toPair argCons++        argCons = zip3 args argTys ts++        maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)++        restFields = listE $ map toPair rest++        (maybes, rest) = partition isMaybe argCons++        maybeToPair (arg, argTy, (field, _, _)) =+            infixApp ([|keyValuePairWith|]+                        `appE` dispatchToJSON jc conName tvMap argTy+                        `appE` toFieldName field)+                     [|(<$>)|]+                     (varE arg)++        toPair (arg, argTy, (field, _, _)) =+            [|keyValuePairWith|]+              `appE` dispatchToJSON jc conName tvMap argTy+              `appE` toFieldName field+              `appE` varE arg++        toFieldName field = [|T.pack|] `appE` fieldLabelExp opts field++    match (conP conName $ map varP args)+          ( normalB+          $ if multiCons+            then case sumEncoding opts of+                   TwoElemArray -> [|toJSON|] `appE` tupE [conStr opts conName, exp]+                   TaggedObject{tagFieldName} ->+                       [|A.object|] `appE`+                         -- TODO: Maybe throw an error in case+                         -- tagFieldName overwrites a field in pairs.+                         infixApp (infixApp [|T.pack tagFieldName|]+                                            [|(.=)|]+                                            (conStr opts conName))+                                  [|(:)|]+                                  pairs+                   ObjectWithSingleField ->+                       [|A.object|] `appE` listE+                         [ infixApp (conTxt opts conName) [|(.=)|] exp ]+                   UntaggedValue -> exp+            else exp+          ) []++-- Infix constructors.+argsToValue jc tjs opts multiCons (InfixC _ conName _) = do+    ([alTy, arTy], tvMap) <- reifyConTys jc tjs conName+    al <- newName "argL"+    ar <- newName "argR"+    match (infixP (varP al) conName (varP ar))+          ( normalB+          $ sumToValue opts multiCons conName+          $ [|toJSON|] `appE` listE [ dispatchToJSON jc conName tvMap aTy+                                        `appE` varE a+                                    | (a, aTy) <- [(al,alTy), (ar,arTy)]+                                    ]+          )+          []+-- Existentially quantified constructors.+argsToValue jc tjs opts multiCons (ForallC _ _ con) =+    argsToValue jc tjs opts multiCons con++#if MIN_VERSION_template_haskell(2,11,0)+-- GADTs.+argsToValue jc tjs opts multiCons (GadtC conNames ts _) =+    argsToValue jc tjs opts multiCons $ NormalC (head conNames) ts++argsToValue jc tjs opts multiCons (RecGadtC conNames ts _) =+    argsToValue jc tjs opts multiCons $ RecC (head conNames) ts+#endif++isMaybe :: (a, b, (c, d, Type)) -> Bool+isMaybe (_, _, (_, _, AppT (ConT t) _)) = t == ''Maybe+isMaybe _                               = False++(<^>) :: ExpQ -> ExpQ -> ExpQ+(<^>) a b = infixApp a [|(E.><)|] b+infixr 6 <^>++(<:>) :: ExpQ -> ExpQ -> ExpQ+(<:>) a b = a <^> [|E.colon|] <^> b+infixr 5 <:>++(<%>) :: ExpQ -> ExpQ -> ExpQ+(<%>) a b = a <^> [|E.comma|] <^> b+infixr 4 <%>++array :: ExpQ -> ExpQ+array exp = [|E.wrapArray|] `appE` exp++object :: ExpQ -> ExpQ+object exp = [|E.wrapObject|] `appE` exp++sumToEncoding :: Options -> Bool -> Name -> Q Exp -> Q Exp+sumToEncoding opts multiCons conName exp+    | multiCons =+        let fexp = exp in+        case sumEncoding opts of+          TwoElemArray ->+            array (encStr opts conName <%> fexp)+          TaggedObject{tagFieldName, contentsFieldName} ->+            object $+            ([|E.text (T.pack tagFieldName)|] <:> encStr opts conName) <%>+            ([|E.text (T.pack contentsFieldName)|] <:> fexp)+          ObjectWithSingleField ->+            object (encStr opts conName <:> fexp)+          UntaggedValue -> exp+    | otherwise = exp++nullarySumToEncoding :: Options -> Bool -> Name -> Q Exp+nullarySumToEncoding opts multiCons conName =+    case sumEncoding opts of+      TaggedObject{tagFieldName} ->+          object $+            [|E.text (T.pack tagFieldName)|] <:> encStr opts conName+      UntaggedValue -> encStr opts conName+      _ -> sumToEncoding opts multiCons conName [e|toEncoding ([] :: [()])|]++-- | Generates code to generate the JSON encoding of a single constructor.+argsToEncoding :: JSONClass -> [(Name, Name)] -> Options -> Bool -> Con -> Q Match+-- Nullary constructors. Generates code that explicitly matches against the+-- constructor even though it doesn't contain data. This is useful to prevent+-- type errors.+argsToEncoding jc tes opts multiCons (NormalC conName []) = do+    ([], _) <- reifyConTys jc tes conName+    match (conP conName [])+          (normalB (nullarySumToEncoding opts multiCons conName))+          []++-- Polyadic constructors with special case for unary constructors.+argsToEncoding jc tes opts multiCons (NormalC conName ts) = do+    (argTys, tvMap) <- reifyConTys jc tes conName+    let len = length ts+    args <- newNameList "arg" len+    js <- case zip args argTys of+            -- Single argument is directly converted.+            [(e,eTy)] -> return (dispatchToEncoding jc conName tvMap eTy+                                   `appE` varE e)+            -- Multiple arguments are converted to a JSON array.+            es  ->+              return (array (foldr1 (<%>) [ dispatchToEncoding jc conName tvMap xTy+                                              `appE` varE x+                                          | (x,xTy) <- es+                                          ]))+    match (conP conName $ map varP args)+          (normalB $ sumToEncoding opts multiCons conName js)+          []++-- Records.+argsToEncoding jc tes opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of+  (True,True,[(_,st,ty)]) -> argsToEncoding jc tes opts multiCons (NormalC conName [(st,ty)])+  _ -> do+    args <- newNameList "arg" $ length ts+    (argTys, tvMap) <- reifyConTys jc tes conName+    let exp = object objBody++        objBody = [|E.econcat|] `appE`+                  ([|intersperse E.comma|] `appE` pairs)+        pairs | omitNothingFields opts = infixApp maybeFields+                                                  [|(++)|]+                                                  restFields+              | otherwise = listE (map toPair argCons)++        argCons = zip3 args argTys ts++        maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)++        restFields = listE (map toPair rest)++        (maybes, rest) = partition isMaybe argCons++        maybeToPair (arg, argTy, (field, _, _)) =+            infixApp+              (infixApp+                (infixE+                  (Just $ toFieldName field <^> [|E.colon|])+                  [|(E.><)|]+                  Nothing)+                [|(.)|]+                (dispatchToEncoding jc conName tvMap argTy))+              [|(<$>)|]+              (varE arg)++        toPair (arg, argTy, (field, _, _)) =+          toFieldName field+            <:> dispatchToEncoding jc conName tvMap argTy+                  `appE` varE arg++        toFieldName field = [|E.text|] `appE`+                            ([|T.pack|] `appE` fieldLabelExp opts field)++    match (conP conName $ map varP args)+          ( normalB+          $ if multiCons+            then case sumEncoding opts of+                   TwoElemArray -> array $+                     encStr opts conName <%>  exp+                   TaggedObject{tagFieldName} -> object $+                     ([|E.text (T.pack tagFieldName)|] <:>+                      encStr opts conName) <%>+                     objBody+                   ObjectWithSingleField -> object $+                     encStr opts conName <:> exp+                   UntaggedValue -> exp+            else exp+          ) []++-- Infix constructors.+argsToEncoding jc tes opts multiCons (InfixC _ conName _) = do+    al <- newName "argL"+    ar <- newName "argR"+    ([alTy,arTy], tvMap) <- reifyConTys jc tes conName+    match (infixP (varP al) conName (varP ar))+          ( normalB+          $ sumToEncoding opts multiCons conName+          $ array (foldr1 (<%>) [ dispatchToEncoding jc conName tvMap aTy+                                    `appE` varE a+                                | (a,aTy) <- [(al,alTy), (ar,arTy)]+                                ])+          )+          []+-- Existentially quantified constructors.+argsToEncoding jc tes opts multiCons (ForallC _ _ con) =+    argsToEncoding jc tes opts multiCons con++#if MIN_VERSION_template_haskell(2,11,0)+-- GADTs.+argsToEncoding jc tes opts multiCons (GadtC conNames ts _) =+    argsToEncoding jc tes opts multiCons $ NormalC (head conNames) ts++argsToEncoding jc tes opts multiCons (RecGadtC conNames ts _) =+    argsToEncoding jc tes opts multiCons $ RecC (head conNames) ts+#endif++--------------------------------------------------------------------------------+-- FromJSON+--------------------------------------------------------------------------------++-- | Generates a 'FromJSON' instance declaration for the given data type or+-- data family instance constructor.+deriveFromJSON :: Options+               -- ^ Encoding options.+               -> Name+               -- ^ Name of the type for which to generate a 'FromJSON' instance+               -- declaration.+               -> Q [Dec]+deriveFromJSON = deriveFromJSONCommon fromJSONClass++-- | Generates a 'FromJSON1' instance declaration for the given data type or+-- data family instance constructor.+deriveFromJSON1 :: Options+                -- ^ Encoding options.+                -> Name+                -- ^ Name of the type for which to generate a 'FromJSON1' instance+                -- declaration.+                -> Q [Dec]+deriveFromJSON1 = deriveFromJSONCommon fromJSON1Class++-- | Generates a 'FromJSON2' instance declaration for the given data type or+-- data family instance constructor.+deriveFromJSON2 :: Options+                -- ^ Encoding options.+                -> Name+                -- ^ Name of the type for which to generate a 'FromJSON3' instance+                -- declaration.+                -> Q [Dec]+deriveFromJSON2 = deriveFromJSONCommon fromJSON2Class++deriveFromJSONCommon :: JSONClass+                     -- ^ The FromJSON variant being derived.+                     -> Options+                     -- ^ Encoding options.+                     -> Name+                     -- ^ Name of the type for which to generate an instance.+                     -- declaration.+                     -> Q [Dec]+deriveFromJSONCommon = deriveJSONClass [(ParseJSON, consFromJSON)]++-- | Generates a lambda expression which parses the JSON encoding of the given+-- data type or data family instance constructor.+mkParseJSON :: Options -- ^ Encoding options.+            -> Name -- ^ Name of the encoded type.+            -> Q Exp+mkParseJSON = mkParseJSONCommon fromJSONClass++-- | Generates a lambda expression which parses the JSON encoding of the given+-- data type or data family instance constructor by using the given parsing+-- function on occurrences of the last type parameter.+mkLiftParseJSON :: Options -- ^ Encoding options.+                -> Name -- ^ Name of the encoded type.+                -> Q Exp+mkLiftParseJSON = mkParseJSONCommon fromJSON1Class++-- | Generates a lambda expression which parses the JSON encoding of the given+-- data type or data family instance constructor by using the given parsing+-- functions on occurrences of the last two type parameters.+mkLiftParseJSON2 :: Options -- ^ Encoding options.+                 -> Name -- ^ Name of the encoded type.+                 -> Q Exp+mkLiftParseJSON2 = mkParseJSONCommon fromJSON2Class++mkParseJSONCommon :: JSONClass -- ^ Which class's method is being derived.+                  -> Options -- ^ Encoding options.+                  -> Name -- ^ Name of the encoded type.+                  -> Q Exp+mkParseJSONCommon = mkFunCommon consFromJSON++-- | Helper function used by both 'deriveFromJSON' and 'mkParseJSON'. Generates+-- code to parse the JSON encoding of a number of constructors. All constructors+-- must be from the same type.+consFromJSON :: JSONClass+             -- ^ The FromJSON variant being derived.+             -> Name+             -- ^ Name of the type to which the constructors belong.+             -> Options+             -- ^ Encoding options+             -> [Con]+             -- ^ Constructors for which to generate JSON parsing code.+             -> Q Exp++consFromJSON _ _ _ [] = error $ "Data.Aeson.TH.consFromJSON: "+                              ++ "Not a single constructor given!"++consFromJSON jc tName opts cons = do+  value <- newName "value"+  pjs   <- newNameList "_pj"  $ arityInt jc+  pjls  <- newNameList "_pjl" $ arityInt jc+  let zippedPJs      = zip pjs pjls+      interleavedPJs = interleave pjs pjls+  lamE (map varP $ interleavedPJs ++ [value]) $ lamExpr value zippedPJs++  where+    lamExpr value pjs = case cons of+      [con] -> parseArgs jc pjs tName opts con (Right value)+      _ | sumEncoding opts == UntaggedValue+            -> parseUntaggedValue pjs cons value+        | otherwise+            -> caseE (varE value) $+                   if allNullaryToStringTag opts && all isNullary cons+                   then allNullaryMatches+                   else mixedMatches pjs++    allNullaryMatches =+      [ do txt <- newName "txt"+           match (conP 'String [varP txt])+                 (guardedB $+                  [ liftM2 (,) (normalG $+                                  infixApp (varE txt)+                                           [|(==)|]+                                           ([|T.pack|] `appE`+                                              conStringE opts conName)+                               )+                               ([|pure|] `appE` conE conName)+                  | con <- cons+                  , let conName = getConName con+                  ]+                  +++                  [ liftM2 (,)+                      (normalG [|otherwise|])+                      ( [|noMatchFail|]+                        `appE` litE (stringL $ show tName)+                        `appE` ([|T.unpack|] `appE` varE txt)+                      )+                  ]+                 )+                 []+      , do other <- newName "other"+           match (varP other)+                 (normalB $ [|noStringFail|]+                    `appE` litE (stringL $ show tName)+                    `appE` ([|valueConName|] `appE` varE other)+                 )+                 []+      ]++    mixedMatches pjs =+        case sumEncoding opts of+          TaggedObject {tagFieldName, contentsFieldName} ->+            parseObject $ parseTaggedObject pjs tagFieldName contentsFieldName+          UntaggedValue -> error "UntaggedValue: Should be handled already"+          ObjectWithSingleField ->+            parseObject $ parseObjectWithSingleField pjs+          TwoElemArray ->+            [ do arr <- newName "array"+                 match (conP 'Array [varP arr])+                       (guardedB+                        [ liftM2 (,) (normalG $ infixApp ([|V.length|] `appE` varE arr)+                                                         [|(==)|]+                                                         (litE $ integerL 2))+                                     (parse2ElemArray pjs arr)+                        , liftM2 (,) (normalG [|otherwise|])+                                     ([|not2ElemArray|]+                                       `appE` litE (stringL $ show tName)+                                       `appE` ([|V.length|] `appE` varE arr))+                        ]+                       )+                       []+            , do other <- newName "other"+                 match (varP other)+                       ( normalB+                         $ [|noArrayFail|]+                             `appE` litE (stringL $ show tName)+                             `appE` ([|valueConName|] `appE` varE other)+                       )+                       []+            ]++    parseObject f =+        [ do obj <- newName "obj"+             match (conP 'Object [varP obj]) (normalB $ f obj) []+        , do other <- newName "other"+             match (varP other)+                   ( normalB+                     $ [|noObjectFail|]+                         `appE` litE (stringL $ show tName)+                         `appE` ([|valueConName|] `appE` varE other)+                   )+                   []+        ]++    parseTaggedObject pjs typFieldName valFieldName obj = do+      conKey <- newName "conKey"+      doE [ bindS (varP conKey)+                  (infixApp (varE obj)+                            [|(.:)|]+                            ([|T.pack|] `appE` stringE typFieldName))+          , noBindS $ parseContents pjs conKey (Left (valFieldName, obj)) 'conNotFoundFailTaggedObject+          ]++    parseUntaggedValue pjs cons' conVal =+        foldr1 (\e e' -> infixApp e [|(<|>)|] e')+               (map (\x -> parseValue pjs x conVal) cons')++    parseValue _pjs (NormalC conName []) conVal = do+      str <- newName "str"+      caseE (varE conVal)+        [ match (conP 'String [varP str])+                (guardedB+                  [ liftM2 (,) (normalG $ infixApp (varE str) [|(==)|] ([|T.pack|] `appE` conStringE opts conName)+                               )+                               ([|pure|] `appE` conE conName)+                  ]+                )+                []+        , matchFailed tName conName "String"+        ]+    parseValue pjs con conVal =+      parseArgs jc pjs tName opts con (Right conVal)+++    parse2ElemArray pjs arr = do+      conKey <- newName "conKey"+      conVal <- newName "conVal"+      let letIx n ix =+              valD (varP n)+                   (normalB ([|V.unsafeIndex|] `appE`+                               varE arr `appE`+                               litE (integerL ix)))+                   []+      letE [ letIx conKey 0+           , letIx conVal 1+           ]+           (caseE (varE conKey)+                  [ do txt <- newName "txt"+                       match (conP 'String [varP txt])+                             (normalB $ parseContents pjs+                                                      txt+                                                      (Right conVal)+                                                      'conNotFoundFail2ElemArray+                             )+                             []+                  , do other <- newName "other"+                       match (varP other)+                             ( normalB+                               $ [|firstElemNoStringFail|]+                                     `appE` litE (stringL $ show tName)+                                     `appE` ([|valueConName|] `appE` varE other)+                             )+                             []+                  ]+           )++    parseObjectWithSingleField pjs obj = do+      conKey <- newName "conKey"+      conVal <- newName "conVal"+      caseE ([e|H.toList|] `appE` varE obj)+            [ match (listP [tupP [varP conKey, varP conVal]])+                    (normalB $ parseContents pjs conKey (Right conVal) 'conNotFoundFailObjectSingleField)+                    []+            , do other <- newName "other"+                 match (varP other)+                       (normalB $ [|wrongPairCountFail|]+                                  `appE` litE (stringL $ show tName)+                                  `appE` ([|show . length|] `appE` varE other)+                       )+                       []+            ]++    parseContents pjs conKey contents errorFun =+        caseE (varE conKey)+              [ match wildP+                      ( guardedB $+                        [ do g <- normalG $ infixApp (varE conKey)+                                                     [|(==)|]+                                                     ([|T.pack|] `appE`+                                                        conNameExp opts con)+                             e <- parseArgs jc pjs tName opts con contents+                             return (g, e)+                        | con <- cons+                        ]+                        +++                        [ liftM2 (,)+                                 (normalG [e|otherwise|])+                                 ( varE errorFun+                                   `appE` litE (stringL $ show tName)+                                   `appE` listE (map ( litE+                                                     . stringL+                                                     . constructorTagModifier opts+                                                     . nameBase+                                                     . getConName+                                                     ) cons+                                                )+                                   `appE` ([|T.unpack|] `appE` varE conKey)+                                 )+                        ]+                      )+                      []+              ]++parseNullaryMatches :: Name -> Name -> [Q Match]+parseNullaryMatches tName conName =+    [ do arr <- newName "arr"+         match (conP 'Array [varP arr])+               (guardedB+                [ liftM2 (,) (normalG $ [|V.null|] `appE` varE arr)+                             ([|pure|] `appE` conE conName)+                , liftM2 (,) (normalG [|otherwise|])+                             (parseTypeMismatch tName conName+                                (litE $ stringL "an empty Array")+                                (infixApp (litE $ stringL "Array of length ")+                                          [|(++)|]+                                          ([|show . V.length|] `appE` varE arr)+                                )+                             )+                ]+               )+               []+    , matchFailed tName conName "Array"+    ]++parseUnaryMatches :: JSONClass -> TyVarMap -> Type -> Name -> [Q Match]+parseUnaryMatches jc tvMap argTy conName =+    [ do arg <- newName "arg"+         match (varP arg)+               ( normalB $ infixApp (conE conName)+                                    [|(<$>)|]+                                    (dispatchParseJSON jc conName tvMap argTy+                                      `appE` varE arg)+               )+               []+    ]++parseRecord :: JSONClass+            -> TyVarMap+            -> [Type]+            -> Options+            -> Name+            -> Name+            -> [VarStrictType]+            -> Name+            -> ExpQ+parseRecord jc tvMap argTys opts tName conName ts obj =+    foldl' (\a b -> infixApp a [|(<*>)|] b)+           (infixApp (conE conName) [|(<$>)|] x)+           xs+    where+      x:xs = [ [|lookupField|]+               `appE` dispatchParseJSON jc conName tvMap argTy+               `appE` litE (stringL $ show tName)+               `appE` litE (stringL $ constructorTagModifier opts $ nameBase conName)+               `appE` varE obj+               `appE` ( [|T.pack|] `appE` fieldLabelExp opts field+                      )+             | ((field, _, _), argTy) <- zip ts argTys+             ]++getValField :: Name -> String -> [MatchQ] -> Q Exp+getValField obj valFieldName matches = do+  val <- newName "val"+  doE [ bindS (varP val) $ infixApp (varE obj)+                                    [|(.:)|]+                                    ([|T.pack|] `appE`+                                       litE (stringL valFieldName))+      , noBindS $ caseE (varE val) matches+      ]++matchCases :: Either (String, Name) Name -> [MatchQ] -> Q Exp+matchCases (Left (valFieldName, obj)) = getValField obj valFieldName+matchCases (Right valName)            = caseE (varE valName)++-- | Generates code to parse the JSON encoding of a single constructor.+parseArgs :: JSONClass -- ^ The FromJSON variant being derived.+          -> [(Name, Name)] -- ^ The names of the encoding/decoding function arguments.+          -> Name -- ^ Name of the type to which the constructor belongs.+          -> Options -- ^ Encoding options.+          -> Con -- ^ Constructor for which to generate JSON parsing code.+          -> Either (String, Name) Name -- ^ Left (valFieldName, objName) or+                                        --   Right valName+          -> Q Exp+-- Nullary constructors.+parseArgs jc pjs _ _ (NormalC conName []) (Left _) = do+  ([], _) <- reifyConTys jc pjs conName+  [|pure|] `appE` conE conName+parseArgs jc pjs tName _ (NormalC conName []) (Right valName) = do+  ([], _) <- reifyConTys jc pjs conName+  caseE (varE valName) $ parseNullaryMatches tName conName++-- Unary constructors.+parseArgs jc pjs _ _ (NormalC conName [_]) contents = do+  ([argTy], tvMap) <- reifyConTys jc pjs conName+  matchCases contents $ parseUnaryMatches jc tvMap argTy conName++-- Polyadic constructors.+parseArgs jc pjs tName _ (NormalC conName ts) contents = do+    (argTys, tvMap) <- reifyConTys jc pjs conName+    let len = genericLength ts+    matchCases contents $ parseProduct jc tvMap argTys tName conName len++-- Records.+parseArgs jc pjs tName opts (RecC conName ts) (Left (_, obj)) = do+    (argTys, tvMap) <- reifyConTys jc pjs conName+    parseRecord jc tvMap argTys opts tName conName ts obj+parseArgs jc pjs tName opts (RecC conName ts) (Right valName) = case (unwrapUnaryRecords opts,ts) of+  (True,[(_,st,ty)])-> parseArgs jc pjs tName opts (NormalC conName [(st,ty)]) (Right valName)+  _ -> do+    obj <- newName "recObj"+    (argTys, tvMap) <- reifyConTys jc pjs conName+    caseE (varE valName)+      [ match (conP 'Object [varP obj]) (normalB $+          parseRecord jc tvMap argTys opts tName conName ts obj) []+      , matchFailed tName conName "Object"+      ]++-- Infix constructors. Apart from syntax these are the same as+-- polyadic constructors.+parseArgs jc pjs tName _ (InfixC _ conName _) contents = do+    (argTys, tvMap) <- reifyConTys jc pjs conName+    matchCases contents $ parseProduct jc tvMap argTys tName conName 2++-- Existentially quantified constructors. We ignore the quantifiers+-- and proceed with the contained constructor.+parseArgs jc pjs tName opts (ForallC _ _ con) contents =+    parseArgs jc pjs tName opts con contents++#if MIN_VERSION_template_haskell(2,11,0)+-- GADTs. We ignore the refined return type and proceed as if it were a+-- NormalC or RecC.+parseArgs jc pjs tName opts (GadtC conNames ts _) contents =+    parseArgs jc pjs tName opts (NormalC (head conNames) ts) contents++parseArgs jc pjs tName opts (RecGadtC conNames ts _) contents =+    parseArgs jc pjs tName opts (RecC (head conNames) ts) contents+#endif++-- | Generates code to parse the JSON encoding of an n-ary+-- constructor.+parseProduct :: JSONClass -- ^ The FromJSON variant being derived.+             -> TyVarMap -- ^ Maps the last type variables to their decoding+                         --   function arguments.+             -> [Type] -- ^ The argument types of the constructor.+             -> Name -- ^ Name of the type to which the constructor belongs.+             -> Name -- ^ 'Con'structor name.+             -> Integer -- ^ 'Con'structor arity.+             -> [Q Match]+parseProduct jc tvMap argTys tName conName numArgs =+    [ do arr <- newName "arr"+         -- List of: "parseJSON (arr `V.unsafeIndex` <IX>)"+         let x:xs = [ dispatchParseJSON jc conName tvMap argTy+                      `appE`+                      infixApp (varE arr)+                               [|V.unsafeIndex|]+                               (litE $ integerL ix)+                    | (argTy, ix) <- zip argTys [0 .. numArgs - 1]+                    ]+         match (conP 'Array [varP arr])+               (normalB $ condE ( infixApp ([|V.length|] `appE` varE arr)+                                           [|(==)|]+                                           (litE $ integerL numArgs)+                                )+                                ( foldl' (\a b -> infixApp a [|(<*>)|] b)+                                         (infixApp (conE conName) [|(<$>)|] x)+                                         xs+                                )+                                ( parseTypeMismatch tName conName+                                    (litE $ stringL $ "Array of length " ++ show numArgs)+                                    ( infixApp (litE $ stringL "Array of length ")+                                               [|(++)|]+                                               ([|show . V.length|] `appE` varE arr)+                                    )+                                )+               )+               []+    , matchFailed tName conName "Array"+    ]++--------------------------------------------------------------------------------+-- Parsing errors+--------------------------------------------------------------------------------++matchFailed :: Name -> Name -> String -> MatchQ+matchFailed tName conName expected = do+  other <- newName "other"+  match (varP other)+        ( normalB $ parseTypeMismatch tName conName+                      (litE $ stringL expected)+                      ([|valueConName|] `appE` varE other)+        )+        []++parseTypeMismatch :: Name -> Name -> ExpQ -> ExpQ -> ExpQ+parseTypeMismatch tName conName expected actual =+    foldl appE+          [|parseTypeMismatch'|]+          [ litE $ stringL $ nameBase conName+          , litE $ stringL $ show tName+          , expected+          , actual+          ]++class LookupField a where+    lookupField :: (Value -> Parser a) -> String -> String+                -> Object -> T.Text -> Parser a++instance OVERLAPPABLE_ LookupField a where+    lookupField = lookupFieldWith++instance LookupField (Maybe a) where+    lookupField pj _ _ = parseOptionalFieldWith pj++lookupFieldWith :: (Value -> Parser a) -> String -> String+                -> Object -> T.Text -> Parser a+lookupFieldWith pj tName rec obj key =+    case H.lookup key obj of+      Nothing -> unknownFieldFail tName rec (T.unpack key)+      Just v  -> pj v <?> Key key++keyValuePairWith :: (v -> Value) -> T.Text -> v -> Pair+keyValuePairWith tj name value = (name, tj value)++unknownFieldFail :: String -> String -> String -> Parser fail+unknownFieldFail tName rec key =+    fail $ printf "When parsing the record %s of type %s the key %s was not present."+                  rec tName key++noArrayFail :: String -> String -> Parser fail+noArrayFail t o = fail $ printf "When parsing %s expected Array but got %s." t o++noObjectFail :: String -> String -> Parser fail+noObjectFail t o = fail $ printf "When parsing %s expected Object but got %s." t o++firstElemNoStringFail :: String -> String -> Parser fail+firstElemNoStringFail t o = fail $ printf "When parsing %s expected an Array of 2 elements where the first element is a String but got %s at the first element." t o++wrongPairCountFail :: String -> String -> Parser fail+wrongPairCountFail t n =+    fail $ printf "When parsing %s expected an Object with a single tag/contents pair but got %s pairs."+                  t n++noStringFail :: String -> String -> Parser fail+noStringFail t o = fail $ printf "When parsing %s expected String but got %s." t o++noMatchFail :: String -> String -> Parser fail+noMatchFail t o =+    fail $ printf "When parsing %s expected a String with the tag of a constructor but got %s." t o++not2ElemArray :: String -> Int -> Parser fail+not2ElemArray t i = fail $ printf "When parsing %s expected an Array of 2 elements but got %i elements" t i++conNotFoundFail2ElemArray :: String -> [String] -> String -> Parser fail+conNotFoundFail2ElemArray t cs o =+    fail $ printf "When parsing %s expected a 2-element Array with a tag and contents element where the tag is one of [%s], but got %s."+                  t (intercalate ", " cs) o++conNotFoundFailObjectSingleField :: String -> [String] -> String -> Parser fail+conNotFoundFailObjectSingleField t cs o =+    fail $ printf "When parsing %s expected an Object with a single tag/contents pair where the tag is one of [%s], but got %s."+                  t (intercalate ", " cs) o++conNotFoundFailTaggedObject :: String -> [String] -> String -> Parser fail+conNotFoundFailTaggedObject t cs o =+    fail $ printf "When parsing %s expected an Object with a tag field where the value is one of [%s], but got %s."+                  t (intercalate ", " cs) o++parseTypeMismatch' :: String -> String -> String -> String -> Parser fail+parseTypeMismatch' conName tName expected actual =+    fail $ printf "When parsing the constructor %s of type %s expected %s but got %s."+                  conName tName expected actual++--------------------------------------------------------------------------------+-- Shared ToJSON and FromJSON code+--------------------------------------------------------------------------------++-- | Functionality common to 'deriveJSON', 'deriveJSON1', and 'deriveJSON2'.+deriveJSONBoth :: (Options -> Name -> Q [Dec])+               -- ^ Function which derives a flavor of 'ToJSON'.+               -> (Options -> Name -> Q [Dec])+               -- ^ Function which derives a flavor of 'FromJSON'.+               -> Options+               -- ^ Encoding options.+               -> Name+               -- ^ Name of the type for which to generate 'ToJSON' and 'FromJSON'+               -- instances.+               -> Q [Dec]+deriveJSONBoth dtj dfj opts name =+    liftM2 (++) (dtj opts name) (dfj opts name)++-- | Functionality common to @deriveToJSON(1)(2)@ and @deriveFromJSON(1)(2)@.+deriveJSONClass :: [(JSONFun, JSONClass -> Name -> Options -> [Con] -> Q Exp)]+                -- ^ The class methods and the functions which derive them.+                -> JSONClass+                -- ^ The class for which to generate an instance.+                -> Options+                -- ^ Encoding options.+                -> Name+                -- ^ Name of the type for which to generate a class instance+                -- declaration.+                -> Q [Dec]+deriveJSONClass consFuns jc opts name =+    withType name $ \name' ctxt tvbs cons mbTys ->+        (:[]) <$> fromCons name' ctxt tvbs cons mbTys+  where+    fromCons :: Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Dec+    fromCons name' ctxt tvbs cons mbTys = do+      (instanceCxt, instanceType)+        <- buildTypeInstance name' jc ctxt tvbs mbTys+      instanceD (return instanceCxt)+                (return instanceType)+                (methodDecs name' cons)++    methodDecs :: Name -> [Con] -> [Q Dec]+    methodDecs name' cons = flip map consFuns $ \(jf, jfMaker) ->+      funD (jsonFunValName jf (arity jc))+           [ clause []+                    (normalB $ jfMaker jc name' opts cons)+                    []+           ]++mkFunCommon :: (JSONClass -> Name -> Options -> [Con] -> Q Exp)+            -- ^ The function which derives the expression.+            -> JSONClass+            -- ^ Which class's method is being derived.+            -> Options+            -- ^ Encoding options.+            -> Name+            -- ^ Name of the encoded type.+            -> Q Exp+mkFunCommon consFun jc opts name = withType name fromCons+  where+    fromCons :: Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Exp+    fromCons name' ctxt tvbs cons mbTys = do+        -- We force buildTypeInstance here since it performs some checks for whether+        -- or not the provided datatype's kind matches the derived method's+        -- typeclass, and produces errors if it can't.+        !_ <- buildTypeInstance name' jc ctxt tvbs mbTys+        consFun jc name' opts cons++dispatchFunByType :: JSONClass+                  -> JSONFun+                  -> Name+                  -> TyVarMap+                  -> Bool -- True if we are using the function argument that works+                          -- on lists (e.g., [a] -> Value). False is we are using+                          -- the function argument that works on single values+                          -- (e.g., a -> Value).+                  -> Type+                  -> Q Exp+dispatchFunByType _ jf _ tvMap list (VarT tyName) =+    varE $ case M.lookup tyName tvMap of+                Just (tfjExp, tfjlExp) -> if list then tfjlExp else tfjExp+                Nothing                -> jsonFunValOrListName list jf Arity0+dispatchFunByType jc jf conName tvMap list (SigT ty _) =+    dispatchFunByType jc jf conName tvMap list ty+dispatchFunByType jc jf conName tvMap list (ForallT _ _ ty) =+    dispatchFunByType jc jf conName tvMap list ty+dispatchFunByType jc jf conName tvMap list ty = do+    let tyCon :: Type+        tyArgs :: [Type]+        tyCon :| tyArgs = unapplyTy ty++        numLastArgs :: Int+        numLastArgs = min (arityInt jc) (length tyArgs)++        lhsArgs, rhsArgs :: [Type]+        (lhsArgs, rhsArgs) = splitAt (length tyArgs - numLastArgs) tyArgs++        tyVarNames :: [Name]+        tyVarNames = M.keys tvMap++    itf <- isTyFamily tyCon+    if any (`mentionsName` tyVarNames) lhsArgs+          || itf && any (`mentionsName` tyVarNames) tyArgs+       then outOfPlaceTyVarError jc conName+       else if any (`mentionsName` tyVarNames) rhsArgs+            then appsE $ varE (jsonFunValOrListName list jf $ toEnum numLastArgs)+                         : zipWith (dispatchFunByType jc jf conName tvMap)+                                   (cycle [False,True])+                                   (interleave rhsArgs rhsArgs)+            else varE $ jsonFunValOrListName list jf Arity0++dispatchToJSON, dispatchToEncoding, dispatchParseJSON+  :: JSONClass -> Name -> TyVarMap -> Type -> Q Exp+dispatchToJSON     jc n tvMap = dispatchFunByType jc ToJSON     n tvMap False+dispatchToEncoding jc n tvMap = dispatchFunByType jc ToEncoding n tvMap False+dispatchParseJSON  jc n tvMap = dispatchFunByType jc ParseJSON  n tvMap False++--------------------------------------------------------------------------------+-- Utility functions+--------------------------------------------------------------------------------++-- | Boilerplate for top level splices.+--+-- The given 'Name' must meet one of two criteria:+--+-- 1. It must be the name of a type constructor of a plain data type or newtype.+-- 2. It must be the name of a data family instance or newtype instance constructor.++-- Any other value will result in an exception.+withType :: Name+         -> (Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q a)+         -- ^ Function that generates the actual code. Will be applied+         -- to the datatype/data family 'Name', datatype context, type+         -- variable binders and constructors extracted from the given+         -- 'Name'. If the 'Name' is from a data family instance+         -- constructor, it will also have its instantiated types;+         -- otherwise, it will be 'Nothing'.+         -> Q a+         -- ^ Resulting value in the 'Q'uasi monad.+withType name f = do+    info <- reify name+    case info of+      TyConI dec ->+        case dec of+#if MIN_VERSION_template_haskell(2,11,0)+          DataD    ctxt _ tvbs _ cons _ -> f name ctxt tvbs cons Nothing+          NewtypeD ctxt _ tvbs _ con  _ -> f name ctxt tvbs [con] Nothing+#else+          DataD    ctxt _ tvbs   cons _ -> f name ctxt tvbs cons Nothing+          NewtypeD ctxt _ tvbs   con  _ -> f name ctxt tvbs [con] Nothing+#endif+          other -> fail $ ns ++ "Unsupported type: " ++ show other+#if MIN_VERSION_template_haskell(2,11,0)+      DataConI _ _ parentName   -> do+#else+      DataConI _ _ parentName _ -> do+#endif+        parentInfo <- reify parentName+        case parentInfo of+#if MIN_VERSION_template_haskell(2,11,0)+          FamilyI (DataFamilyD _ tvbs _) decs ->+#else+          FamilyI (FamilyD DataFam _ tvbs _) decs ->+#endif+            let instDec = flip find decs $ \dec -> case dec of+#if MIN_VERSION_template_haskell(2,11,0)+                  DataInstD    _ _ _ _ cons _ -> any ((name ==) . getConName) cons+                  NewtypeInstD _ _ _ _ con  _ -> name == getConName con+#else+                  DataInstD    _ _ _   cons _ -> any ((name ==) . getConName) cons+                  NewtypeInstD _ _ _   con  _ -> name == getConName con+#endif+                  _ -> error $ ns ++ "Must be a data or newtype instance."+             in case instDec of+#if MIN_VERSION_template_haskell(2,11,0)+                  Just (DataInstD    ctxt _ instTys _ cons _) -> f parentName ctxt tvbs cons $ Just instTys+                  Just (NewtypeInstD ctxt _ instTys _ con  _) -> f parentName ctxt tvbs [con] $ Just instTys+#else+                  Just (DataInstD    ctxt _ instTys   cons _) -> f parentName ctxt tvbs cons $ Just instTys+                  Just (NewtypeInstD ctxt _ instTys   con  _) -> f parentName ctxt tvbs [con] $ Just instTys+#endif+                  _ -> fail $ ns +++                    "Could not find data or newtype instance constructor."+          _ -> fail $ ns ++ "Data constructor " ++ show name +++            " is not from a data family instance constructor."+#if MIN_VERSION_template_haskell(2,11,0)+      FamilyI DataFamilyD{} _ ->+#else+      FamilyI (FamilyD DataFam _ _ _) _ ->+#endif+        fail $ ns +++          "Cannot use a data family name. Use a data family instance constructor instead."+      _ -> fail $ ns ++ "I need the name of a plain data type constructor, "+                      ++ "or a data family instance constructor."+  where+    ns :: String+    ns = "Data.Aeson.TH.withType: "++-- | Infer the context and instance head needed for a FromJSON or ToJSON instance.+buildTypeInstance :: Name+                  -- ^ The type constructor or data family name+                  -> JSONClass+                  -- ^ The typeclass to derive+                  -> Cxt+                  -- ^ The datatype context+                  -> [TyVarBndr]+                  -- ^ The type variables from the data type/data family declaration+                  -> Maybe [Type]+                  -- ^ 'Just' the types used to instantiate a data family instance,+                  -- or 'Nothing' if it's a plain data type+                  -> Q (Cxt, Type)+                  -- ^ The resulting 'Cxt' and 'Type' to use in a class instance+-- Plain data type/newtype case+buildTypeInstance tyConName jc dataCxt tvbs Nothing =+    let varTys :: [Type]+        varTys = map tvbToType tvbs+    in buildTypeInstanceFromTys tyConName jc dataCxt varTys False+-- Data family instance case+--+-- The CPP is present to work around a couple of annoying old GHC bugs.+-- See Note [Polykinded data families in Template Haskell]+buildTypeInstance dataFamName jc dataCxt tvbs (Just instTysAndKinds) = do+#if !(MIN_VERSION_template_haskell(2,8,0)) || MIN_VERSION_template_haskell(2,10,0)+    let instTys :: [Type]+        instTys = zipWith stealKindForType tvbs instTysAndKinds+#else+    let kindVarNames :: [Name]+        kindVarNames = nub $ concatMap (tyVarNamesOfType . tvbKind) tvbs++        numKindVars :: Int+        numKindVars = length kindVarNames++        givenKinds, givenKinds' :: [Kind]+        givenTys                :: [Type]+        (givenKinds, givenTys) = splitAt numKindVars instTysAndKinds+        givenKinds' = map sanitizeStars givenKinds++        -- A GHC 7.6-specific bug requires us to replace all occurrences of+        -- (ConT GHC.Prim.*) with StarT, or else Template Haskell will reject it.+        -- Luckily, (ConT GHC.Prim.*) only seems to occur in this one spot.+        sanitizeStars :: Kind -> Kind+        sanitizeStars = go+          where+            go :: Kind -> Kind+            go (AppT t1 t2)                 = AppT (go t1) (go t2)+            go (SigT t k)                   = SigT (go t) (go k)+            go (ConT n) | n == starKindName = StarT+            go t                            = t++            -- It's quite awkward to import * from GHC.Prim, so we'll just+            -- hack our way around it.+            starKindName :: Name+            starKindName = mkNameG_tc "ghc-prim" "GHC.Prim" "*"++    -- If we run this code with GHC 7.8, we might have to generate extra type+    -- variables to compensate for any type variables that Template Haskell+    -- eta-reduced away.+    -- See Note [Polykinded data families in Template Haskell]+    xTypeNames <- newNameList "tExtra" (length tvbs - length givenTys)++    let xTys   :: [Type]+        xTys = map VarT xTypeNames+        -- ^ Because these type variables were eta-reduced away, we can only+        --   determine their kind by using stealKindForType. Therefore, we mark+        --   them as VarT to ensure they will be given an explicit kind annotation+        --   (and so the kind inference machinery has the right information).++        substNamesWithKinds :: [(Name, Kind)] -> Type -> Type+        substNamesWithKinds nks t = foldr' (uncurry substNameWithKind) t nks++        -- The types from the data family instance might not have explicit kind+        -- annotations, which the kind machinery needs to work correctly. To+        -- compensate, we use stealKindForType to explicitly annotate any+        -- types without kind annotations.+        instTys :: [Type]+        instTys = map (substNamesWithKinds (zip kindVarNames givenKinds'))+                  -- Note that due to a GHC 7.8-specific bug+                  -- (see Note [Polykinded data families in Template Haskell]),+                  -- there may be more kind variable names than there are kinds+                  -- to substitute. But this is OK! If a kind is eta-reduced, it+                  -- means that is was not instantiated to something more specific,+                  -- so we need not substitute it. Using stealKindForType will+                  -- grab the correct kind.+                $ zipWith stealKindForType tvbs (givenTys ++ xTys)+#endif+    buildTypeInstanceFromTys dataFamName jc dataCxt instTys True++-- For the given Types, generate an instance context and head.+buildTypeInstanceFromTys :: Name+                         -- ^ The type constructor or data family name+                         -> JSONClass+                         -- ^ The typeclass to derive+                         -> Cxt+                         -- ^ The datatype context+                         -> [Type]+                         -- ^ The types to instantiate the instance with+                         -> Bool+                         -- ^ True if it's a data family, False otherwise+                         -> Q (Cxt, Type)+buildTypeInstanceFromTys tyConName jc dataCxt varTysOrig isDataFamily = do+    -- Make sure to expand through type/kind synonyms! Otherwise, the+    -- eta-reduction check might get tripped up over type variables in a+    -- synonym that are actually dropped.+    -- (See GHC Trac #11416 for a scenario where this actually happened.)+    varTysExp <- mapM expandSyn varTysOrig++    let remainingLength :: Int+        remainingLength = length varTysOrig - arityInt jc++        droppedTysExp :: [Type]+        droppedTysExp = drop remainingLength varTysExp++        droppedStarKindStati :: [StarKindStatus]+        droppedStarKindStati = map canRealizeKindStar droppedTysExp++    -- Check there are enough types to drop and that all of them are either of+    -- kind * or kind k (for some kind variable k). If not, throw an error.+    when (remainingLength < 0 || elem NotKindStar droppedStarKindStati) $+      derivingKindError jc tyConName++    let droppedKindVarNames :: [Name]+        droppedKindVarNames = catKindVarNames droppedStarKindStati++        -- Substitute kind * for any dropped kind variables+        varTysExpSubst :: [Type]+        varTysExpSubst = map (substNamesWithKindStar droppedKindVarNames) varTysExp++        remainingTysExpSubst, droppedTysExpSubst :: [Type]+        (remainingTysExpSubst, droppedTysExpSubst) =+          splitAt remainingLength varTysExpSubst++        -- All of the type variables mentioned in the dropped types+        -- (post-synonym expansion)+        droppedTyVarNames :: [Name]+        droppedTyVarNames = concatMap tyVarNamesOfType droppedTysExpSubst++    -- If any of the dropped types were polykinded, ensure that they are of kind *+    -- after substituting * for the dropped kind variables. If not, throw an error.+    unless (all hasKindStar droppedTysExpSubst) $+      derivingKindError jc tyConName++    let preds    :: [Maybe Pred]+        kvNames  :: [[Name]]+        kvNames' :: [Name]+        -- Derive instance constraints (and any kind variables which are specialized+        -- to * in those constraints)+        (preds, kvNames) = unzip $ map (deriveConstraint jc) remainingTysExpSubst+        kvNames' = concat kvNames++        -- Substitute the kind variables specialized in the constraints with *+        remainingTysExpSubst' :: [Type]+        remainingTysExpSubst' =+          map (substNamesWithKindStar kvNames') remainingTysExpSubst++        -- We now substitute all of the specialized-to-* kind variable names with+        -- *, but in the original types, not the synonym-expanded types. The reason+        -- we do this is a superficial one: we want the derived instance to resemble+        -- the datatype written in source code as closely as possible. For example,+        -- for the following data family instance:+        --+        --   data family Fam a+        --   newtype instance Fam String = Fam String+        --+        -- We'd want to generate the instance:+        --+        --   instance C (Fam String)+        --+        -- Not:+        --+        --   instance C (Fam [Char])+        remainingTysOrigSubst :: [Type]+        remainingTysOrigSubst =+          map (substNamesWithKindStar (union droppedKindVarNames kvNames'))+            $ take remainingLength varTysOrig++        remainingTysOrigSubst' :: [Type]+        -- See Note [Kind signatures in derived instances] for an explanation+        -- of the isDataFamily check.+        remainingTysOrigSubst' =+          if isDataFamily+             then remainingTysOrigSubst+             else map unSigT remainingTysOrigSubst++        instanceCxt :: Cxt+        instanceCxt = catMaybes preds++        instanceType :: Type+        instanceType = AppT (ConT $ jsonClassName jc)+                     $ applyTyCon tyConName remainingTysOrigSubst'++    -- If the datatype context mentions any of the dropped type variables,+    -- we can't derive an instance, so throw an error.+    when (any (`predMentionsName` droppedTyVarNames) dataCxt) $+      datatypeContextError tyConName instanceType+    -- Also ensure the dropped types can be safely eta-reduced. Otherwise,+    -- throw an error.+    unless (canEtaReduce remainingTysExpSubst' droppedTysExpSubst) $+      etaReductionError instanceType+    return (instanceCxt, instanceType)++-- | Attempt to derive a constraint on a Type. If successful, return+-- Just the constraint and any kind variable names constrained to *.+-- Otherwise, return Nothing and the empty list.+--+-- See Note [Type inference in derived instances] for the heuristics used to+-- come up with constraints.+deriveConstraint :: JSONClass -> Type -> (Maybe Pred, [Name])+deriveConstraint jc t+  | not (isTyVar t) = (Nothing, [])+  | hasKindStar t   = (Just (applyCon (jcConstraint Arity0) tName), [])+  | otherwise = case hasKindVarChain 1 t of+      Just ns | jcArity >= Arity1+              -> (Just (applyCon (jcConstraint Arity1) tName), ns)+      _ -> case hasKindVarChain 2 t of+           Just ns | jcArity == Arity2+                   -> (Just (applyCon (jcConstraint Arity2) tName), ns)+           _ -> (Nothing, [])+  where+    tName :: Name+    tName = varTToName t++    jcArity :: Arity+    jcArity = arity jc++    jcConstraint :: Arity -> Name+    jcConstraint = jsonClassName . JSONClass (direction jc)++{-+Note [Polykinded data families in Template Haskell]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++In order to come up with the correct instance context and head for an instance, e.g.,++  instance C a => C (Data a) where ...++We need to know the exact types and kinds used to instantiate the instance. For+plain old datatypes, this is simple: every type must be a type variable, and+Template Haskell reliably tells us the type variables and their kinds.++Doing the same for data families proves to be much harder for three reasons:++1. On any version of Template Haskell, it may not tell you what an instantiated+   type's kind is. For instance, in the following data family instance:++     data family Fam (f :: * -> *) (a :: *)+     data instance Fam f a++   Then if we use TH's reify function, it would tell us the TyVarBndrs of the+   data family declaration are:++     [KindedTV f (AppT (AppT ArrowT StarT) StarT),KindedTV a StarT]++   and the instantiated types of the data family instance are:++     [VarT f1,VarT a1]++   We can't just pass [VarT f1,VarT a1] to buildTypeInstanceFromTys, since we+   have no way of knowing their kinds. Luckily, the TyVarBndrs tell us what the+   kind is in case an instantiated type isn't a SigT, so we use the stealKindForType+   function to ensure all of the instantiated types are SigTs before passing them+   to buildTypeInstanceFromTys.+2. On GHC 7.6 and 7.8, a bug is present in which Template Haskell lists all of+   the specified kinds of a data family instance efore any of the instantiated+   types. Fortunately, this is easy to deal with: you simply count the number of+   distinct kind variables in the data family declaration, take that many elements+   from the front of the  Types list of the data family instance, substitute the+   kind variables with their respective instantiated kinds (which you took earlier),+   and proceed as normal.+3. On GHC 7.8, an even uglier bug is present (GHC Trac #9692) in which Template+   Haskell might not even list all of the Types of a data family instance, since+   they are eta-reduced away! And yes, kinds can be eta-reduced too.++   The simplest workaround is to count how many instantiated types are missing from+   the list and generate extra type variables to use in their place. Luckily, we+   needn't worry much if its kind was eta-reduced away, since using stealKindForType+   will get it back.++Note [Kind signatures in derived instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++It is possible to put explicit kind signatures into the derived instances, e.g.,++  instance C a => C (Data (f :: * -> *)) where ...++But it is preferable to avoid this if possible. If we come up with an incorrect+kind signature (which is entirely possible, since Template Haskell doesn't always+have the best track record with reifying kind signatures), then GHC will flat-out+reject the instance, which is quite unfortunate.++Plain old datatypes have the advantage that you can avoid using any kind signatures+at all in their instances. This is because a datatype declaration uses all type+variables, so the types that we use in a derived instance uniquely determine their+kinds. As long as we plug in the right types, the kind inferencer can do the rest+of the work. For this reason, we use unSigT to remove all kind signatures before+splicing in the instance context and head.++Data family instances are trickier, since a data family can have two instances that+are distinguished by kind alone, e.g.,++  data family Fam (a :: k)+  data instance Fam (a :: * -> *)+  data instance Fam (a :: *)++If we dropped the kind signatures for C (Fam a), then GHC will have no way of+knowing which instance we are talking about. To avoid this scenario, we always+include explicit kind signatures in data family instances. There is a chance that+the inferred kind signatures will be incorrect, but if so, we can always fall back+on the mk- functions.++Note [Type inference in derived instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Type inference is can be tricky to get right, and we want to avoid recreating the+entirety of GHC's type inferencer in Template Haskell. For this reason, we will+probably never come up with derived instance contexts that are as accurate as+GHC's. But that doesn't mean we can't do anything! There are a couple of simple+things we can do to make instance contexts that work for 80% of use cases:++1. If one of the last type parameters is polykinded, then its kind will be+   specialized to * in the derived instance. We note what kind variable the type+   parameter had and substitute it with * in the other types as well. For example,+   imagine you had++     data Data (a :: k) (b :: k)++   Then you'd want to derived instance to be:++     instance C (Data (a :: *))++   Not:++     instance C (Data (a :: k))++2. We naïvely come up with instance constraints using the following criteria:++   (i)   If there's a type parameter n of kind *, generate a ToJSON n/FromJSON n+         constraint.+   (ii)  If there's a type parameter n of kind k1 -> k2 (where k1/k2 are * or kind+         variables), then generate a ToJSON1 n/FromJSON1 n constraint, and if+         k1/k2 are kind variables, then substitute k1/k2 with * elsewhere in the+         types. We must consider the case where they are kind variables because+         you might have a scenario like this:++           newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1)+             = Compose (f (g a))++         Which would have a derived ToJSON1 instance of:++           instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Compose f g) where ...+   (iii) If there's a type parameter n of kind k1 -> k2 -> k3 (where k1/k2/k3 are+         * or kind variables), then generate a ToJSON2 n/FromJSON2 n constraint+         and perform kind substitution as in the other cases.+-}++-- Determines the types of a constructor's arguments as well as the last type+-- parameters (mapped to their encoding/decoding functions), expanding through+-- any type synonyms.+--+-- The type parameters are determined on a constructor-by-constructor basis since+-- they may be refined to be particular types in a GADT.+reifyConTys :: JSONClass+            -> [(Name, Name)]+            -> Name+            -> Q ([Type], TyVarMap)+reifyConTys jc tpjs conName = do+    info  <- reify conName+    (ctxt, uncTy) <- case info of+        DataConI _ ty _+#if !(MIN_VERSION_template_haskell(2,11,0))+                _+#endif+                -> fmap uncurryTy (expandSyn ty)+        _ -> error "Must be a data constructor"+    let (argTys, [resTy]) = NE.splitAt (NE.length uncTy - 1) uncTy+        unapResTy = unapplyTy resTy+        -- If one of the last type variables is refined to a particular type+        -- (i.e., not truly polymorphic), we mark it with Nothing and filter+        -- it out later, since we only apply encoding/decoding functions to+        -- arguments of a type that it (1) one of the last type variables,+        -- and (2) of a truly polymorphic type.+        jArity = arityInt jc+        mbTvNames = map varTToNameMaybe $+                        NE.drop (NE.length unapResTy - jArity) unapResTy+        -- We use M.fromList to ensure that if there are any duplicate type+        -- variables (as can happen in a GADT), the rightmost type variable gets+        -- associated with the show function.+        --+        -- See Note [Matching functions with GADT type variables]+        tvMap = M.fromList+                    . catMaybes -- Drop refined types+                    $ zipWith (\mbTvName tpj ->+                                  fmap (\tvName -> (tvName, tpj)) mbTvName)+                              mbTvNames tpjs+    if (any (`predMentionsName` M.keys tvMap) ctxt+         || M.size tvMap < jArity)+         && not (allowExQuant jc)+       then existentialContextError conName+       else return (argTys, tvMap)++{-+Note [Matching functions with GADT type variables]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++When deriving ToJSON2, there is a tricky corner case to consider:++  data Both a b where+    BothCon :: x -> x -> Both x x++Which encoding functions should be applied to which arguments of BothCon?+We have a choice, since both the function of type (a -> Value) and of type+(b -> Value) can be applied to either argument. In such a scenario, the+second encoding function takes precedence over the first encoding function, so the+derived ToJSON2 instance would be something like:++  instance ToJSON2 Both where+    liftToJSON2 tj1 tj2 p (BothCon x1 x2) = Array $ create $ do+      mv <- unsafeNew 2+      unsafeWrite mv 0 (tj1 x1)+      unsafeWrite mv 1 (tj2 x2)+      return mv++This is not an arbitrary choice, as this definition ensures that+liftToJSON2 toJSON = liftToJSON for a derived ToJSON1 instance for+Both.+-}++-- A mapping of type variable Names to their encoding/decoding function Names.+-- For example, in a ToJSON2 declaration, a TyVarMap might look like+--+-- { a ~> (tj1, tjl1)+-- , b ~> (tj2, tjl2) }+--+-- where a and b are the last two type variables of the datatype, tj1 and tjl1 are+-- the function arguments of types (a -> Value) and ([a] -> Value), and tj2 and tjl2+-- are the function arguments of types (b -> Value) and ([b] -> Value).+type TyVarMap = Map Name (Name, Name)++-- | If a VarT is missing an explicit kind signature, steal it from a TyVarBndr.+stealKindForType :: TyVarBndr -> Type -> Type+stealKindForType tvb t@VarT{} = SigT t (tvbKind tvb)+stealKindForType _   t        = t++-- | Extracts the kind from a type variable binder.+tvbKind :: TyVarBndr -> Kind+#if MIN_VERSION_template_haskell(2,8,0)+tvbKind (PlainTV  _  ) = StarT+#else+tvbKind (PlainTV  _  ) = StarK+#endif+tvbKind (KindedTV _ k) = k++tvbToType :: TyVarBndr -> Type+tvbToType (PlainTV n)    = VarT n+tvbToType (KindedTV n k) = SigT (VarT n) k++-- | Returns True if a Type has kind *.+hasKindStar :: Type -> Bool+hasKindStar VarT{}         = True+#if MIN_VERSION_template_haskell(2,8,0)+hasKindStar (SigT _ StarT) = True+#else+hasKindStar (SigT _ StarK) = True+#endif+hasKindStar _              = False++-- Returns True is a kind is equal to *, or if it is a kind variable.+isStarOrVar :: Kind -> Bool+#if MIN_VERSION_template_haskell(2,8,0)+isStarOrVar StarT  = True+isStarOrVar VarT{} = True+#else+isStarOrVar StarK  = True+#endif+isStarOrVar _      = False++-- Generate a list of fresh names with a common prefix, and numbered suffixes.+newNameList :: String -> Int -> Q [Name]+newNameList prefix len = mapM newName [prefix ++ show n | n <- [1..len]]++-- Gets all of the type/kind variable names mentioned somewhere in a Type.+tyVarNamesOfType :: Type -> [Name]+tyVarNamesOfType = go+  where+    go :: Type -> [Name]+    go (AppT t1 t2) = go t1 ++ go t2+    go (SigT t _k)  = go t+#if MIN_VERSION_template_haskell(2,8,0)+                           ++ go _k+#endif+    go (VarT n)     = [n]+    go _            = []++-- | Gets all of the type/kind variable names mentioned somewhere in a Kind.+tyVarNamesOfKind :: Kind -> [Name]+#if MIN_VERSION_template_haskell(2,8,0)+tyVarNamesOfKind = tyVarNamesOfType+#else+tyVarNamesOfKind _ = [] -- There are no kind variables+#endif++-- | @hasKindVarChain n kind@ Checks if @kind@ is of the form+-- k_0 -> k_1 -> ... -> k_(n-1), where k0, k1, ..., and k_(n-1) can be * or+-- kind variables.+hasKindVarChain :: Int -> Type -> Maybe [Name]+hasKindVarChain kindArrows t =+  let uk = uncurryKind (tyKind t)+  in if (NE.length uk - 1 == kindArrows) && F.all isStarOrVar uk+        then Just (concatMap tyVarNamesOfKind uk)+        else Nothing++-- | If a Type is a SigT, returns its kind signature. Otherwise, return *.+tyKind :: Type -> Kind+tyKind (SigT _ k) = k+tyKind _          = starK++-- | Extract Just the Name from a type variable. If the argument Type is not a+-- type variable, return Nothing.+varTToNameMaybe :: Type -> Maybe Name+varTToNameMaybe (VarT n)   = Just n+varTToNameMaybe (SigT t _) = varTToNameMaybe t+varTToNameMaybe _          = Nothing++-- | Extract the Name from a type variable. If the argument Type is not a+-- type variable, throw an error.+varTToName :: Type -> Name+varTToName = fromMaybe (error "Not a type variable!") . varTToNameMaybe++-- | Extracts the name from a constructor.+getConName :: Con -> Name+getConName (NormalC name _)  = name+getConName (RecC name _)     = name+getConName (InfixC _ name _) = name+getConName (ForallC _ _ con) = getConName con+#if MIN_VERSION_template_haskell(2,11,0)+getConName (GadtC    names _ _) = head names+getConName (RecGadtC names _ _) = head names+#endif++interleave :: [a] -> [a] -> [a]+interleave (a1:a1s) (a2:a2s) = a1:a2:interleave a1s a2s+interleave _        _        = []++-- | Fully applies a type constructor to its type variables.+applyTyCon :: Name -> [Type] -> Type+applyTyCon = foldl' AppT . ConT++-- | Is the given type a variable?+isTyVar :: Type -> Bool+isTyVar (VarT _)   = True+isTyVar (SigT t _) = isTyVar t+isTyVar _          = False++-- | Is the given type a type family constructor (and not a data family constructor)?+isTyFamily :: Type -> Q Bool+isTyFamily (ConT n) = do+    info <- reify n+    return $ case info of+#if MIN_VERSION_template_haskell(2,11,0)+         FamilyI OpenTypeFamilyD{} _       -> True+#else+         FamilyI (FamilyD TypeFam _ _ _) _ -> True+#endif+#if MIN_VERSION_template_haskell(2,9,0)+         FamilyI ClosedTypeFamilyD{} _     -> True+#endif+         _ -> False+isTyFamily _ = return False++-- | Peel off a kind signature from a Type (if it has one).+unSigT :: Type -> Type+unSigT (SigT t _) = t+unSigT t          = t++-- | Are all of the items in a list (which have an ordering) distinct?+--+-- This uses Set (as opposed to nub) for better asymptotic time complexity.+allDistinct :: Ord a => [a] -> Bool+allDistinct = allDistinct' Set.empty+  where+    allDistinct' :: Ord a => Set a -> [a] -> Bool+    allDistinct' uniqs (x:xs)+        | x `Set.member` uniqs = False+        | otherwise            = allDistinct' (Set.insert x uniqs) xs+    allDistinct' _ _           = True++-- | Does the given type mention any of the Names in the list?+mentionsName :: Type -> [Name] -> Bool+mentionsName = go+  where+    go :: Type -> [Name] -> Bool+    go (AppT t1 t2) names = go t1 names || go t2 names+    go (SigT t _k)  names = go t names+#if MIN_VERSION_template_haskell(2,8,0)+                              || go _k names+#endif+    go (VarT n)     names = n `elem` names+    go _            _     = False++-- | Does an instance predicate mention any of the Names in the list?+predMentionsName :: Pred -> [Name] -> Bool+#if MIN_VERSION_template_haskell(2,10,0)+predMentionsName = mentionsName+#else+predMentionsName (ClassP n tys) names = n `elem` names || any (`mentionsName` names) tys+predMentionsName (EqualP t1 t2) names = mentionsName t1 names || mentionsName t2 names+#endif++-- | Split an applied type into its individual components. For example, this:+--+-- @+-- Either Int Char+-- @+--+-- would split to this:+--+-- @+-- [Either, Int, Char]+-- @+unapplyTy :: Type -> NonEmpty Type+unapplyTy = NE.reverse . go+  where+    go :: Type -> NonEmpty Type+    go (AppT t1 t2)    = t2 <| go t1+    go (SigT t _)      = go t+    go (ForallT _ _ t) = go t+    go t               = t :| []++-- | Split a type signature by the arrows on its spine. For example, this:+--+-- @+-- forall a b. (a ~ b) => (a -> b) -> Char -> ()+-- @+--+-- would split to this:+--+-- @+-- (a ~ b, [a -> b, Char, ()])+-- @+uncurryTy :: Type -> (Cxt, NonEmpty Type)+uncurryTy (AppT (AppT ArrowT t1) t2) =+  let (ctxt, tys) = uncurryTy t2+  in (ctxt, t1 <| tys)+uncurryTy (SigT t _) = uncurryTy t+uncurryTy (ForallT _ ctxt t) =+  let (ctxt', tys) = uncurryTy t+  in (ctxt ++ ctxt', tys)+uncurryTy t = ([], t :| [])++-- | Like uncurryType, except on a kind level.+uncurryKind :: Kind -> NonEmpty Kind+#if MIN_VERSION_template_haskell(2,8,0)+uncurryKind = snd . uncurryTy+#else+uncurryKind (ArrowK k1 k2) = k1 <| uncurryKind k2+uncurryKind k              = k :| []+#endif++createKindChain :: Int -> Kind+createKindChain = go starK+  where+    go :: Kind -> Int -> Kind+    go k !0 = k+#if MIN_VERSION_template_haskell(2,8,0)+    go k !n = go (AppT (AppT ArrowT StarT) k) (n - 1)+#else+    go k !n = go (ArrowK StarK k) (n - 1)+#endif++-- | Makes a string literal expression from a constructor's name.+conNameExp :: Options -> Con -> Q Exp+conNameExp opts = litE+                . stringL+                . constructorTagModifier opts+                . nameBase+                . getConName++-- | Creates a string literal expression from a record field label.+fieldLabelExp :: Options -- ^ Encoding options+              -> Name+              -> Q Exp+fieldLabelExp opts = litE . stringL . fieldLabelModifier opts . nameBase++-- | The name of the outermost 'Value' constructor.+valueConName :: Value -> String+valueConName (Object _) = "Object"+valueConName (Array  _) = "Array"+valueConName (String _) = "String"+valueConName (Number _) = "Number"+valueConName (Bool   _) = "Boolean"+valueConName Null       = "Null"++applyCon :: Name -> Name -> Pred+applyCon con t =+#if MIN_VERSION_template_haskell(2,10,0)+          AppT (ConT con) (VarT t)+#else+          ClassP con [VarT t]+#endif++-- | Checks to see if the last types in a data family instance can be safely eta-+-- reduced (i.e., dropped), given the other types. This checks for three conditions:+--+-- (1) All of the dropped types are type variables+-- (2) All of the dropped types are distinct+-- (3) None of the remaining types mention any of the dropped types+canEtaReduce :: [Type] -> [Type] -> Bool+canEtaReduce remaining dropped =+       all isTyVar dropped+    && allDistinct droppedNames -- Make sure not to pass something of type [Type], since Type+                                -- didn't have an Ord instance until template-haskell-2.10.0.0+    && not (any (`mentionsName` droppedNames) remaining)+  where+    droppedNames :: [Name]+    droppedNames = map varTToName dropped++-------------------------------------------------------------------------------+-- Expanding type synonyms+-------------------------------------------------------------------------------++-- | Expands all type synonyms in a type. Written by Dan Rosén in the+-- @genifunctors@ package (licensed under BSD3).+expandSyn :: Type -> Q Type+expandSyn (ForallT tvs ctx t) = ForallT tvs ctx <$> expandSyn t+expandSyn t@AppT{}            = expandSynApp t []+expandSyn t@ConT{}            = expandSynApp t []+expandSyn (SigT t k)          = do t' <- expandSyn t+                                   k' <- expandSynKind k+                                   return (SigT t' k')+expandSyn t                   = return t++expandSynKind :: Kind -> Q Kind+#if MIN_VERSION_template_haskell(2,8,0)+expandSynKind = expandSyn+#else+expandSynKind = return -- There are no kind synonyms to deal with+#endif++expandSynApp :: Type -> [Type] -> Q Type+expandSynApp (AppT t1 t2) ts = do+    t2' <- expandSyn t2+    expandSynApp t1 (t2':ts)+expandSynApp (ConT n) ts | nameBase n == "[]" = return $ foldl' AppT ListT ts+expandSynApp t@(ConT n) ts = do+    info <- reify n+    case info of+        TyConI (TySynD _ tvs rhs) ->+            let (ts', ts'') = splitAt (length tvs) ts+                subs = mkSubst tvs ts'+                rhs' = substType subs rhs+             in expandSynApp rhs' ts''+        _ -> return $ foldl' AppT t ts+expandSynApp t ts = do+    t' <- expandSyn t+    return $ foldl' AppT t' ts++type TypeSubst = Map Name Type+type KindSubst = Map Name Kind++mkSubst :: [TyVarBndr] -> [Type] -> TypeSubst+mkSubst vs ts =+   let vs' = map un vs+       un (PlainTV v)    = v+       un (KindedTV v _) = v+   in M.fromList $ zip vs' ts++substType :: TypeSubst -> Type -> Type+substType subs (ForallT v c t) = ForallT v c $ substType subs t+substType subs t@(VarT n)      = M.findWithDefault t n subs+substType subs (AppT t1 t2)    = AppT (substType subs t1) (substType subs t2)+substType subs (SigT t k)      = SigT (substType subs t)+#if MIN_VERSION_template_haskell(2,8,0)+                                      (substType subs k)+#else+                                      k+#endif+substType _ t                  = t++substKind :: KindSubst -> Type -> Type+#if MIN_VERSION_template_haskell(2,8,0)+substKind = substType+#else+substKind _ t = t -- There are no kind variables!+#endif++substNameWithKind :: Name -> Kind -> Type -> Type+substNameWithKind n k = substKind (M.singleton n k)++substNamesWithKindStar :: [Name] -> Type -> Type+substNamesWithKindStar ns t = foldr' (flip substNameWithKind starK) t ns++-------------------------------------------------------------------------------+-- Error messages+-------------------------------------------------------------------------------++-- | Either the given data type doesn't have enough type variables, or one of+-- the type variables to be eta-reduced cannot realize kind *.+derivingKindError :: JSONClass -> Name -> Q a+derivingKindError jc tyConName = fail+  . showString "Cannot derive well-kinded instance of form ‘"+  . showString className+  . showChar ' '+  . showParen True+    ( showString (nameBase tyConName)+    . showString " ..."+    )+  . showString "‘\n\tClass "+  . showString className+  . showString " expects an argument of kind "+  . showString (pprint . createKindChain $ arityInt jc)+  $ ""+  where+    className :: String+    className = nameBase $ jsonClassName jc++-- | One of the last type variables cannot be eta-reduced (see the canEtaReduce+-- function for the criteria it would have to meet).+etaReductionError :: Type -> Q a+etaReductionError instanceType = fail $+    "Cannot eta-reduce to an instance of form \n\tinstance (...) => "+    ++ pprint instanceType++-- | The data type has a DatatypeContext which mentions one of the eta-reduced+-- type variables.+datatypeContextError :: Name -> Type -> Q a+datatypeContextError dataName instanceType = fail+    . showString "Can't make a derived instance of ‘"+    . showString (pprint instanceType)+    . showString "‘:\n\tData type ‘"+    . showString (nameBase dataName)+    . showString "‘ must not have a class context involving the last type argument(s)"+    $ ""++-- | The data type mentions one of the n eta-reduced type variables in a place other+-- than the last nth positions of a data type in a constructor's field.+outOfPlaceTyVarError :: JSONClass -> Name -> a+outOfPlaceTyVarError jc conName = error+    . showString "Constructor ‘"+    . showString (nameBase conName)+    . showString "‘ must only use its last "+    . shows n+    . showString " type variable(s) within the last "+    . shows n+    . showString " argument(s) of a data type"+    $ ""+  where+    n :: Int+    n = arityInt jc++-- | The data type has an existential constraint which mentions one of the+-- eta-reduced type variables.+existentialContextError :: Name -> a+existentialContextError conName = error+  . showString "Constructor ‘"+  . showString (nameBase conName)+  . showString "‘ must be truly polymorphic in the last argument(s) of the data type"+  $ ""++-------------------------------------------------------------------------------+-- Class-specific constants+-------------------------------------------------------------------------------++-- | A representation of the arity of the ToJSON/FromJSON typeclass being derived.+data Arity = Arity0 | Arity1 | Arity2+  deriving (Enum, Eq, Ord)++-- | Whether ToJSON(1)(2) or FromJSON(1)(2) is being derived.+data Direction = To | From++-- | A representation of which typeclass method is being spliced in.+data JSONFun = ToJSON | ToEncoding | ParseJSON++-- | A representation of which typeclass is being derived.+data JSONClass = JSONClass { direction :: Direction, arity :: Arity }++toJSONClass, toJSON1Class, toJSON2Class,+    fromJSONClass, fromJSON1Class, fromJSON2Class :: JSONClass+toJSONClass    = JSONClass To   Arity0+toJSON1Class   = JSONClass To   Arity1+toJSON2Class   = JSONClass To   Arity2+fromJSONClass  = JSONClass From Arity0+fromJSON1Class = JSONClass From Arity1+fromJSON2Class = JSONClass From Arity2++jsonClassName :: JSONClass -> Name+jsonClassName (JSONClass To   Arity0) = ''ToJSON+jsonClassName (JSONClass To   Arity1) = ''ToJSON1+jsonClassName (JSONClass To   Arity2) = ''ToJSON2+jsonClassName (JSONClass From Arity0) = ''FromJSON+jsonClassName (JSONClass From Arity1) = ''FromJSON1+jsonClassName (JSONClass From Arity2) = ''FromJSON2++jsonFunValName :: JSONFun -> Arity -> Name+jsonFunValName ToJSON     Arity0 = 'toJSON+jsonFunValName ToJSON     Arity1 = 'liftToJSON+jsonFunValName ToJSON     Arity2 = 'liftToJSON2+jsonFunValName ToEncoding Arity0 = 'toEncoding+jsonFunValName ToEncoding Arity1 = 'liftToEncoding+jsonFunValName ToEncoding Arity2 = 'liftToEncoding2+jsonFunValName ParseJSON  Arity0 = 'parseJSON+jsonFunValName ParseJSON  Arity1 = 'liftParseJSON+jsonFunValName ParseJSON  Arity2 = 'liftParseJSON2++jsonFunListName :: JSONFun -> Arity -> Name+jsonFunListName ToJSON     Arity0 = 'toJSONList+jsonFunListName ToJSON     Arity1 = 'liftToJSONList+jsonFunListName ToJSON     Arity2 = 'liftToJSONList2+jsonFunListName ToEncoding Arity0 = 'toEncodingList+jsonFunListName ToEncoding Arity1 = 'liftToEncodingList+jsonFunListName ToEncoding Arity2 = 'liftToEncodingList2+jsonFunListName ParseJSON  Arity0 = 'parseJSONList+jsonFunListName ParseJSON  Arity1 = 'liftParseJSONList+jsonFunListName ParseJSON  Arity2 = 'liftParseJSONList2++jsonFunValOrListName :: Bool -- e.g., toJSONList if True, toJSON if False+                     -> JSONFun -> Arity -> Name+jsonFunValOrListName False = jsonFunValName+jsonFunValOrListName True  = jsonFunListName++arityInt :: JSONClass -> Int+arityInt = fromEnum . arity++allowExQuant :: JSONClass -> Bool+allowExQuant (JSONClass To _) = True+allowExQuant _                = False++-------------------------------------------------------------------------------+-- StarKindStatus+-------------------------------------------------------------------------------++-- | Whether a type is not of kind *, is of kind *, or is a kind variable.+data StarKindStatus = NotKindStar+                    | KindStar+                    | IsKindVar Name+  deriving Eq++-- | Does a Type have kind * or k (for some kind variable k)?+canRealizeKindStar :: Type -> StarKindStatus+canRealizeKindStar t+  | hasKindStar t = KindStar+  | otherwise = case t of+#if MIN_VERSION_template_haskell(2,8,0)+                     SigT _ (VarT k) -> IsKindVar k+#endif+                     _               -> NotKindStar++-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.+-- Otherwise, returns 'Nothing'.+starKindStatusToName :: StarKindStatus -> Maybe Name+starKindStatusToName (IsKindVar n) = Just n+starKindStatusToName _             = Nothing++-- | Concat together all of the StarKindStatuses that are IsKindVar and extract+-- the kind variables' Names out.+catKindVarNames :: [StarKindStatus] -> [Name]+catKindVarNames = mapMaybe starKindStatusToName
+ Data/Aeson/Text.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module:      Data.Aeson.Text+-- Copyright:   (c) 2012-2016 Bryan O'Sullivan+--              (c) 2011 MailRank, Inc.+-- License:     BSD3+-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>+-- Stability:   experimental+-- Portability: portable+--+-- Most frequently, you'll probably want to encode straight to UTF-8+-- (the standard JSON encoding) using 'encode'.+--+-- You can use the conversions to 'Builder's when embedding JSON messages as+-- parts of a protocol.+module Data.Aeson.Text+    (+      encodeToLazyText+    , encodeToTextBuilder+    ) where++import Prelude ()+import Prelude.Compat++import Data.Aeson.Types (Value(..), ToJSON(..))+import Data.Aeson.Encoding (encodingToLazyByteString)+import Data.Monoid ((<>))+import Data.Scientific (FPFormat(..), Scientific, base10Exponent)+import Data.Text.Lazy.Builder+import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)+import Numeric (showHex)+import qualified Data.HashMap.Strict as H+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Encoding as LT+import qualified Data.Vector as V++-- | Encode a JSON 'Value' to a "Data.Text.Lazy"+--+-- /Note:/ uses 'toEncoding'+encodeToLazyText :: ToJSON a => a -> LT.Text+encodeToLazyText = LT.decodeUtf8 . encodingToLazyByteString . toEncoding++-- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be+-- embedded efficiently in a text-based protocol.+--+-- If you are going to immediately encode straight to a+-- 'L.ByteString', it is more efficient to use 'encodeToBuilder'+-- instead.+--+-- /Note:/ Uses 'toJSON'+encodeToTextBuilder :: ToJSON a => a -> Builder+encodeToTextBuilder =+    go . toJSON+  where+    go Null       = {-# SCC "go/Null" #-} "null"+    go (Bool b)   = {-# SCC "go/Bool" #-} if b then "true" else "false"+    go (Number s) = {-# SCC "go/Number" #-} fromScientific s+    go (String s) = {-# SCC "go/String" #-} string s+    go (Array v)+        | V.null v = {-# SCC "go/Array" #-} "[]"+        | otherwise = {-# SCC "go/Array" #-}+                      singleton '[' <>+                      go (V.unsafeHead v) <>+                      V.foldr f (singleton ']') (V.unsafeTail v)+      where f a z = singleton ',' <> go a <> z+    go (Object m) = {-# SCC "go/Object" #-}+        case H.toList m of+          (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs+          _      -> "{}"+      where f a z     = singleton ',' <> one a <> z+            one (k,v) = string k <> singleton ':' <> go v++string :: T.Text -> Builder+string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'+  where+    quote q = case T.uncons t of+                Nothing      -> fromText h+                Just (!c,t') -> fromText h <> escape c <> quote t'+        where (h,t) = {-# SCC "break" #-} T.break isEscape q+    isEscape c = c == '\"' ||+                 c == '\\' ||+                 c < '\x20'+    escape '\"' = "\\\""+    escape '\\' = "\\\\"+    escape '\n' = "\\n"+    escape '\r' = "\\r"+    escape '\t' = "\\t"++    escape c+        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h+        | otherwise  = singleton c+        where h = showHex (fromEnum c) ""++fromScientific :: Scientific -> Builder+fromScientific s = formatScientificBuilder format prec s+  where+    (format, prec)+      | base10Exponent s < 0 = (Generic, Nothing)+      | otherwise            = (Fixed,   Just 0)
Data/Aeson/Types.hs view
@@ -37,13 +37,43 @@     , KeyValue(..)     , modifyFailure +    -- ** Keys for maps+    , ToJSONKey(..)+    , ToJSONKeyFunction(..)+    , toJSONKeyText+    , contramapToJSONKeyFunction+    , FromJSONKey(..)+    , FromJSONKeyFunction(..)+    , fromJSONKeyCoerce+    , coerceFromJSONKeyFunction+    , mapFromJSONKeyFunction++    -- ** Liftings to unary and binary type constructors+    , FromJSON1(..)+    , parseJSON1+    , FromJSON2(..)+    , parseJSON2+    , ToJSON1(..)+    , toJSON1+    , toEncoding1+    , ToJSON2(..)+    , toJSON2+    , toEncoding2+     -- ** Generic JSON classes     , GFromJSON(..)+    , FromArgs(..)     , GToJSON(..)     , GToEncoding(..)+    , ToArgs(..)+    , Zero+    , One     , genericToJSON+    , genericLiftToJSON     , genericToEncoding+    , genericLiftToEncoding     , genericParseJSON+    , genericLiftParseJSON      -- * Inspecting @'Value's@     , withObject@@ -61,6 +91,10 @@     , (.!=)     , object +    , listEncoding+    , listValue+    , listParser+     -- * Generic and TH encoding configuration     , Options(..)     , SumEncoding(..)@@ -70,7 +104,15 @@     , defaultTaggedObject     ) where -import Data.Aeson.Encode.Functions (foldable, pairs)-import Data.Aeson.Types.Generic ()-import Data.Aeson.Types.Instances+import Prelude ()+import Prelude.Compat++import Data.Aeson.Encoding (Encoding, unsafeToEncoding, fromEncoding, Series, pairs)+import Data.Aeson.Types.Class import Data.Aeson.Types.Internal+import Data.Foldable (toList)++-- | Encode a 'Foldable' as a JSON array.+foldable :: (Foldable t, ToJSON a) => t a -> Encoding+foldable = toEncoding . toList+{-# INLINE foldable #-}
Data/Aeson/Types/Class.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE CPP, DefaultSignatures, FlexibleContexts #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeSynonymInstances #-}  -- | -- Module:      Data.Aeson.Types.Class@@ -16,259 +22,69 @@     -- * Core JSON classes       FromJSON(..)     , ToJSON(..)+    -- * Liftings to unary and binary type constructors+    , FromJSON1(..)+    , parseJSON1+    , FromJSON2(..)+    , parseJSON2+    , ToJSON1(..)+    , toJSON1+    , toEncoding1+    , ToJSON2(..)+    , toJSON2+    , toEncoding2     -- * Generic JSON classes     , GFromJSON(..)+    , FromArgs(..)     , GToJSON(..)     , GToEncoding(..)+    , ToArgs(..)+    , Zero+    , One     , genericToJSON+    , genericLiftToJSON     , genericToEncoding+    , genericLiftToEncoding     , genericParseJSON+    , genericLiftParseJSON+    -- * Classes and types for map keys+    , ToJSONKey(..)+    , ToJSONKeyFunction(..)+    , toJSONKeyText+    , contramapToJSONKeyFunction+    , FromJSONKey(..)+    , FromJSONKeyFunction(..)+    , fromJSONKeyCoerce+    , coerceFromJSONKeyFunction+    , mapFromJSONKeyFunction     -- * Object key-value pairs     , KeyValue(..)-    -- * Functions needed for documentation-    , typeMismatch-    ) where -import Data.Aeson.Types.Internal-import Data.Text (Text)-import GHC.Generics (Generic, Rep, from, to)-import qualified Data.Aeson.Encode.Builder as E---- | Class of generic representation types ('Rep') that can be converted to--- JSON.-class GToJSON f where-    -- | This method (applied to 'defaultOptions') is used as the-    -- default generic implementation of 'toJSON'.-    gToJSON :: Options -> f a -> Value---- | Class of generic representation types ('Rep') that can be converted to--- a JSON 'Encoding'.-class GToEncoding f where-    -- | This method (applied to 'defaultOptions') can be used as the-    -- default generic implementation of 'toEncoding'.-    gToEncoding :: Options -> f a -> Encoding---- | Class of generic representation types ('Rep') that can be converted from JSON.-class GFromJSON f where-    -- | This method (applied to 'defaultOptions') is used as the-    -- default generic implementation of 'parseJSON'.-    gParseJSON :: Options -> Value -> Parser (f a)---- | A configurable generic JSON creator. This function applied to--- 'defaultOptions' is used as the default for 'toJSON' when the type--- is an instance of 'Generic'.-genericToJSON :: (Generic a, GToJSON (Rep a)) => Options -> a -> Value-genericToJSON opts = gToJSON opts . from---- | A configurable generic JSON encoder. This function applied to--- 'defaultOptions' is used as the default for 'toEncoding' when the type--- is an instance of 'Generic'.-genericToEncoding :: (Generic a, GToEncoding (Rep a)) => Options -> a -> Encoding-genericToEncoding opts = gToEncoding opts . from---- | A configurable generic JSON decoder. This function applied to--- 'defaultOptions' is used as the default for 'parseJSON' when the--- type is an instance of 'Generic'.-genericParseJSON :: (Generic a, GFromJSON (Rep a)) => Options -> Value -> Parser a-genericParseJSON opts = fmap to . gParseJSON opts---- | A type that can be converted to JSON.------ An example type and instance:------ @--- \-- Allow ourselves to write 'Text' literals.--- {-\# LANGUAGE OverloadedStrings #-}------ data Coord = Coord { x :: Double, y :: Double }------ instance ToJSON Coord where---   toJSON (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]------   toEncoding (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)--- @------ Instead of manually writing your 'ToJSON' instance, there are two options--- to do it automatically:------ * "Data.Aeson.TH" provides Template Haskell functions which will derive an--- instance at compile time. The generated instance is optimized for your type--- so will probably be more efficient than the following two options:------ * The compiler can provide a default generic implementation for--- 'toJSON'.------ To use the second, simply add a @deriving 'Generic'@ clause to your--- datatype and declare a 'ToJSON' instance for your datatype without giving--- definitions for 'toJSON' or 'toEncoding'.------ For example, the previous example can be simplified to a more--- minimal instance:------ @--- {-\# LANGUAGE DeriveGeneric \#-}------ import "GHC.Generics"------ data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'------ instance ToJSON Coord where---     toEncoding = 'genericToEncoding' 'defaultOptions'--- @------ Why do we provide an implementation for 'toEncoding' here?  The--- 'toEncoding' function is a relatively new addition to this class.--- To allow users of older versions of this library to upgrade without--- having to edit all of their instances or encounter surprising--- incompatibilities, the default implementation of 'toEncoding' uses--- 'toJSON'.  This produces correct results, but since it performs an--- intermediate conversion to a 'Value', it will be less efficient--- than directly emitting an 'Encoding'.  Our one-liner definition of--- 'toEncoding' above bypasses the intermediate 'Value'.------ If @DefaultSignatures@ doesn't give exactly the results you want,--- you can customize the generic encoding with only a tiny amount of--- effort, using 'genericToJSON' and 'genericToEncoding' with your--- preferred 'Options':------ @--- instance ToJSON Coord where---     toJSON     = 'genericToJSON' 'defaultOptions'---     toEncoding = 'genericToEncoding' 'defaultOptions'--- @-class ToJSON a where-    -- | Convert a Haskell value to a JSON-friendly intermediate type.-    toJSON     :: a -> Value--    default toJSON :: (Generic a, GToJSON (Rep a)) => a -> Value-    toJSON = genericToJSON defaultOptions--    -- | Encode a Haskell value as JSON.-    ---    -- The default implementation of this method creates an-    -- intermediate 'Value' using 'toJSON'.  This provides-    -- source-level compatibility for people upgrading from older-    -- versions of this library, but obviously offers no performance-    -- advantage.-    ---    -- To benefit from direct encoding, you /must/ provide an-    -- implementation for this method.  The easiest way to do so is by-    -- having your types implement 'Generic' using the @DeriveGeneric@-    -- extension, and then have GHC generate a method body as follows.-    ---    -- @-    -- instance ToJSON Coord where-    --     toEncoding = 'genericToEncoding' 'defaultOptions'-    -- @--    toEncoding :: a -> Encoding-    toEncoding = Encoding . E.encodeToBuilder . toJSON-    {-# INLINE toEncoding #-}---- | A type that can be converted from JSON, with the possibility of--- failure.------ In many cases, you can get the compiler to generate parsing code--- for you (see below).  To begin, let's cover writing an instance by--- hand.------ There are various reasons a conversion could fail.  For example, an--- 'Object' could be missing a required key, an 'Array' could be of--- the wrong size, or a value could be of an incompatible type.------ The basic ways to signal a failed conversion are as follows:------ * 'empty' and 'mzero' work, but are terse and uninformative------ * 'fail' yields a custom error message------ * 'typeMismatch' produces an informative message for cases when the--- value encountered is not of the expected type------ An example type and instance:------ @--- \-- Allow ourselves to write 'Text' literals.--- {-\# LANGUAGE OverloadedStrings #-}------ data Coord = Coord { x :: Double, y :: Double }------ instance FromJSON Coord where---   parseJSON ('Object' v) = Coord    '<$>'---                          v '.:' \"x\" '<*>'---                          v '.:' \"y\"------   \-- We do not expect a non-'Object' value here.---   \-- We could use 'mzero' to fail, but 'typeMismatch'---   \-- gives a much more informative error message.---   parseJSON invalid    = 'typeMismatch' \"Coord\" invalid--- @------ Instead of manually writing your 'FromJSON' instance, there are two options--- to do it automatically:------ * "Data.Aeson.TH" provides Template Haskell functions which will derive an--- instance at compile time. The generated instance is optimized for your type--- so will probably be more efficient than the following two options:------ * The compiler can provide a default generic implementation for--- 'parseJSON'.------ To use the second, simply add a @deriving 'Generic'@ clause to your--- datatype and declare a 'FromJSON' instance for your datatype without giving--- a definition for 'parseJSON'.------ For example, the previous example can be simplified to just:------ @--- {-\# LANGUAGE DeriveGeneric \#-}------ import "GHC.Generics"------ data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'------ instance FromJSON Coord--- @------ If @DefaultSignatures@ doesn't give exactly the results you want,--- you can customize the generic decoding with only a tiny amount of--- effort, using 'genericParseJSON' with your preferred 'Options':------ @--- instance FromJSON Coord where---     parseJSON = 'genericParseJSON' 'defaultOptions'--- @+    -- * List functions+    , listEncoding+    , listValue+    , listParser -class FromJSON a where-    parseJSON :: Value -> Parser a+      -- * Inspecting @'Value's@+    , withObject+    , withText+    , withArray+    , withNumber+    , withScientific+    , withBool -    default parseJSON :: (Generic a, GFromJSON (Rep a)) => Value -> Parser a-    parseJSON = genericParseJSON defaultOptions+    -- * Functions+    , fromJSON+    , ifromJSON+    , (.:)+    , (.:?)+    , (.:!)+    , (.!=)+    , typeMismatch+    ) where --- | A key-value pair for encoding a JSON object.-class KeyValue kv where-    (.=) :: ToJSON v => Text -> v -> kv-    infixr 8 .=+import Prelude () --- | Fail parsing due to a type mismatch, with a descriptive message.------ Example usage:------ @--- instance FromJSON Coord where---   parseJSON ('Object' v) = {- type matches, life is good -}---   parseJSON wat        = 'typeMismatch' \"Coord\" wat--- @-typeMismatch :: String -- ^ The name of the type you are trying to parse.-             -> Value  -- ^ The actual value encountered.-             -> Parser a-typeMismatch expected actual =-    fail $ "expected " ++ expected ++ ", encountered " ++ name-  where-    name = case actual of-             Object _ -> "Object"-             Array _  -> "Array"-             String _ -> "String"-             Number _ -> "Number"-             Bool _   -> "Boolean"-             Null     -> "Null"+import Data.Aeson.Types.FromJSON+import Data.Aeson.Types.Generic (One, Zero)+import Data.Aeson.Types.ToJSON
+ Data/Aeson/Types/FromJSON.hs view
@@ -0,0 +1,2032 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++#if __GLASGOW_HASKELL__ >= 706+{-# LANGUAGE PolyKinds #-}+#endif++#include "overlapping-compat.h"++-- TODO: Drop this when we remove support for Data.Attoparsec.Number+{-# OPTIONS_GHC -fno-warn-deprecations #-}++module Data.Aeson.Types.FromJSON+    (+    -- * Core JSON classes+      FromJSON(..)+    -- * Liftings to unary and binary type constructors+    , FromJSON1(..)+    , parseJSON1+    , FromJSON2(..)+    , parseJSON2+    -- * Generic JSON classes+    , GFromJSON(..)+    , FromArgs(..)+    , genericParseJSON+    , genericLiftParseJSON+    -- * Classes and types for map keys+    , FromJSONKey(..)+    , FromJSONKeyFunction(..)+    , fromJSONKeyCoerce+    , coerceFromJSONKeyFunction+    , mapFromJSONKeyFunction++    -- * List functions+    , listParser++    -- * Inspecting @'Value's@+    , withObject+    , withText+    , withArray+    , withNumber+    , withScientific+    , withBool++    -- * Functions+    , fromJSON+    , ifromJSON+    , (.:)+    , (.:?)+    , (.:!)+    , (.!=)+    , typeMismatch++    -- * Internal+    , parseOptionalFieldWith+    ) where++import Prelude ()+import Prelude.Compat++import Control.Applicative ((<|>), Const(..))+import Control.Monad ((<=<), zipWithM)+import Data.Aeson.Internal.Functions (mapKey)+import Data.Aeson.Types.Generic+import Data.Aeson.Types.Internal+import Data.Attoparsec.Number (Number(..))+import Data.Bits (unsafeShiftR)+import Data.Fixed (Fixed, HasResolution)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))+import Data.Functor.Product (Product(..))+import Data.Functor.Sum (Sum(..))+import Data.Hashable (Hashable(..))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>), Dual(..), First (..), Last (..))+import Data.Proxy (Proxy(..))+import Data.Ratio ((%), Ratio)+import Data.Scientific (Scientific)+import Data.Tagged (Tagged(..))+import Data.Text (Text, pack, unpack)+import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)+import Data.Time.Format (parseTime)+import Data.Time.Locale.Compat (defaultTimeLocale)+import Data.Traversable as Tr (sequence)+import Data.Vector (Vector)+import Data.Version (Version, parseVersion)+import Data.Word (Word16, Word32, Word64, Word8)+import Foreign.Storable (Storable)+import GHC.Generics+import Numeric.Natural (Natural)+import Text.ParserCombinators.ReadP (readP_to_S)+import qualified Data.Aeson.Parser.Time as Time+import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)+import qualified Data.DList as DList+import qualified Data.HashMap.Strict as H+import qualified Data.HashSet as HashSet+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Map as M+import qualified Data.Scientific as Scientific+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as LT+import qualified Data.Tree as Tree+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Primitive as VP+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Unboxed as VU+import Unsafe.Coerce (unsafeCoerce)++#ifndef HAS_COERCIBLE+#define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 707)+#endif++#if HAS_COERCIBLE+import Data.Coerce (Coercible, coerce)+coerce' :: Coercible a b => a -> b+coerce' = coerce+#else+coerce' :: a -> b+coerce' = unsafeCoerce+#endif++parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a+parseIndexedJSON p idx value = p value <?> Index idx+{-# INLINE parseIndexedJSON #-}++parseIndexedJSONPair :: (Value -> Parser a) -> (Value -> Parser b) -> Int -> Value -> Parser (a, b)+parseIndexedJSONPair keyParser valParser idx value = p value <?> Index idx+  where+    p = withArray "(k,v)" $ \ab ->+        let n = V.length ab+        in if n == 2+             then (,) <$> parseJSONElemAtIndex keyParser 0 ab+                      <*> parseJSONElemAtIndex valParser 1 ab+             else fail $ "cannot unpack array of length " +++                         show n ++ " into a pair"+{-# INLINE parseIndexedJSONPair #-}++parseJSONElemAtIndex :: (Value -> Parser a) -> Int -> V.Vector Value -> Parser a+parseJSONElemAtIndex p idx ary = p (V.unsafeIndex ary idx) <?> Index idx++scientificToNumber :: Scientific -> Number+scientificToNumber s+    | e < 0     = D $ Scientific.toRealFloat s+    | otherwise = I $ c * 10 ^ e+  where+    e = Scientific.base10Exponent s+    c = Scientific.coefficient s+{-# INLINE scientificToNumber #-}++parseRealFloat :: RealFloat a => String -> Value -> Parser a+parseRealFloat _        (Number s) = pure $ Scientific.toRealFloat s+parseRealFloat _        Null       = pure (0/0)+parseRealFloat expected v          = typeMismatch expected v+{-# INLINE parseRealFloat #-}++parseIntegralFromScientific :: forall a. Integral a => String -> Scientific -> Parser a+parseIntegralFromScientific expected s =+    case Scientific.floatingOrInteger s :: Either Double a of+        Right x -> pure x+        Left _  -> fail $ "Floating number specified for " ++ expected ++ ": " ++ show s+{-# INLINE parseIntegralFromScientific #-}++parseIntegral :: Integral a => String -> Value -> Parser a+parseIntegral expected =+    withScientific expected $ parseIntegralFromScientific expected+{-# INLINE parseIntegral #-}++parseBoundedIntegralFromScientific :: (Bounded a, Integral a) => String -> Scientific -> Parser a+parseBoundedIntegralFromScientific expected s = maybe+    (fail $ expected ++ " is either floating or will cause over or underflow: " ++ show s)+    pure+    (Scientific.toBoundedInteger s)+{-# INLINE parseBoundedIntegralFromScientific #-}++parseBoundedIntegral :: (Bounded a, Integral a) => String -> Value -> Parser a+parseBoundedIntegral expected =+    withScientific expected $ parseBoundedIntegralFromScientific expected+{-# INLINE parseBoundedIntegral #-}++parseScientificText :: Text -> Parser Scientific+parseScientificText+    = either fail pure+    . A.parseOnly (A.scientific <* A.endOfInput)+    . T.encodeUtf8++parseIntegralText :: Integral a => String -> Text -> Parser a+parseIntegralText expected t =+    parseScientificText t >>= parseIntegralFromScientific expected+{-# INLINE parseIntegralText #-}++parseBoundedIntegralText :: (Bounded a, Integral a) => String -> Text -> Parser a+parseBoundedIntegralText expected t =+    parseScientificText t >>= parseBoundedIntegralFromScientific expected++parseOptionalFieldWith :: (Value -> Parser (Maybe a))+                       -> Object -> Text -> Parser (Maybe a)+parseOptionalFieldWith pj obj key =+    case H.lookup key obj of+     Nothing -> pure Nothing+     Just v  -> pj v <?> Key key+{-# INLINE parseOptionalFieldWith #-}++-------------------------------------------------------------------------------+-- Generics+-------------------------------------------------------------------------------++-- | Class of generic representation types that can be converted from JSON.+class GFromJSON arity f where+    -- | This method (applied to 'defaultOptions') is used as the+    -- default generic implementation of 'parseJSON' (if the @arity@ is 'Zero')+    -- or 'liftParseJSON' (if the @arity@ is 'One').+    gParseJSON :: Options -> FromArgs arity a -> Value -> Parser (f a)++-- | A 'FromArgs' value either stores nothing (for 'FromJSON') or it stores the+-- two function arguments that decode occurrences of the type parameter (for+-- 'FromJSON1').+data FromArgs arity a where+    NoFromArgs :: FromArgs Zero a+    From1Args  :: (Value -> Parser a) -> (Value -> Parser [a]) -> FromArgs One a++-- | A configurable generic JSON decoder. This function applied to+-- 'defaultOptions' is used as the default for 'parseJSON' when the+-- type is an instance of 'Generic'.+genericParseJSON :: (Generic a, GFromJSON Zero (Rep a))+                 => Options -> Value -> Parser a+genericParseJSON opts = fmap to . gParseJSON opts NoFromArgs++-- | A configurable generic JSON decoder. This function applied to+-- 'defaultOptions' is used as the default for 'liftParseJSON' when the+-- type is an instance of 'Generic1'.+genericLiftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f))+                     => Options -> (Value -> Parser a) -> (Value -> Parser [a])+                     -> Value -> Parser (f a)+genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)++-------------------------------------------------------------------------------+-- Class+-------------------------------------------------------------------------------++-- | A type that can be converted from JSON, with the possibility of+-- failure.+--+-- In many cases, you can get the compiler to generate parsing code+-- for you (see below).  To begin, let's cover writing an instance by+-- hand.+--+-- There are various reasons a conversion could fail.  For example, an+-- 'Object' could be missing a required key, an 'Array' could be of+-- the wrong size, or a value could be of an incompatible type.+--+-- The basic ways to signal a failed conversion are as follows:+--+-- * 'empty' and 'mzero' work, but are terse and uninformative+--+-- * 'fail' yields a custom error message+--+-- * 'typeMismatch' produces an informative message for cases when the+-- value encountered is not of the expected type+--+-- An example type and instance:+--+-- @+-- \-- Allow ourselves to write 'Text' literals.+-- {-\# LANGUAGE OverloadedStrings #-}+--+-- data Coord = Coord { x :: Double, y :: Double }+--+-- instance FromJSON Coord where+--   parseJSON ('Object' v) = Coord    '<$>'+--                          v '.:' \"x\" '<*>'+--                          v '.:' \"y\"+--+--   \-- We do not expect a non-'Object' value here.+--   \-- We could use 'mzero' to fail, but 'typeMismatch'+--   \-- gives a much more informative error message.+--   parseJSON invalid    = 'typeMismatch' \"Coord\" invalid+-- @+--+-- Instead of manually writing your 'FromJSON' instance, there are two options+-- to do it automatically:+--+-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an+-- instance at compile time. The generated instance is optimized for your type+-- so will probably be more efficient than the following two options:+--+-- * The compiler can provide a default generic implementation for+-- 'parseJSON'.+--+-- To use the second, simply add a @deriving 'Generic'@ clause to your+-- datatype and declare a 'FromJSON' instance for your datatype without giving+-- a definition for 'parseJSON'.+--+-- For example, the previous example can be simplified to just:+--+-- @+-- {-\# LANGUAGE DeriveGeneric \#-}+--+-- import "GHC.Generics"+--+-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'+--+-- instance FromJSON Coord+-- @+--+-- If @DefaultSignatures@ doesn't give exactly the results you want,+-- you can customize the generic decoding with only a tiny amount of+-- effort, using 'genericParseJSON' with your preferred 'Options':+--+-- @+-- instance FromJSON Coord where+--     parseJSON = 'genericParseJSON' 'defaultOptions'+-- @++class FromJSON a where+    parseJSON :: Value -> Parser a++    default parseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a+    parseJSON = genericParseJSON defaultOptions++    parseJSONList :: Value -> Parser [a]+    parseJSONList (Array a)+        = zipWithM (parseIndexedJSON parseJSON) [0..]+        . V.toList+        $ a++    parseJSONList v = typeMismatch "[a]" v++-------------------------------------------------------------------------------+--  Classes and types for map keys+-------------------------------------------------------------------------------++-- | Read the docs for 'ToJSONKey' first. This class is a conversion+--   in the opposite direction. If you have a newtype wrapper around 'Text',+--   the recommended way to define instances is with generalized newtype deriving:+--+--   > newtype SomeId = SomeId { getSomeId :: Text }+--   >   deriving (Eq,Ord,Hashable,FromJSONKey)+--+class FromJSONKey a where+    -- | Strategy for parsing the key of a map-like container.+    fromJSONKey :: FromJSONKeyFunction a+    default fromJSONKey :: FromJSON a => FromJSONKeyFunction a+    fromJSONKey = FromJSONKeyValue parseJSON++    -- | This is similar in spirit to the 'readList' method of 'Read'.+    --   It makes it possible to give 'String' keys special treatment+    --   without using @OverlappingInstances@. End users should always+    --   be able to use the default implementation of this method.+    fromJSONKeyList :: FromJSONKeyFunction [a]+    default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]+    fromJSONKeyList = FromJSONKeyValue parseJSON++-- | With GHC 7.8+ we carry around @'Coercible' 'Text' a@ dictionary,+-- to give us an assurance that the program will not segfault.+-- Unfortunately we cannot enforce that the 'Eq' instances or the+-- 'Hashable' instances for 'Text' and @a@ agree.+--+-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'+-- can be inspected, but cannot be constructed.+data CoerceText a where+#if HAS_COERCIBLE+    CoerceText :: Coercible Text a => CoerceText a+#else+    CoerceText :: CoerceText a+#endif++-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the+--   'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'+--   instance. The other three data constructors for this type all correspond to+--   'ToJSONKeyText'. Strictly speaking, 'FromJSONKeyTextParser' is more powerful than+--   'FromJSONKeyText', which is in turn more powerful than 'FromJSONKeyCoerce'.+--   For performance reasons, these exist as three options instead of one.+data FromJSONKeyFunction a+    = FromJSONKeyCoerce !(CoerceText a)+      -- ^ uses 'coerce' ('unsafeCoerce' in older GHCs)+    | FromJSONKeyText !(Text -> a)+      -- ^ conversion from 'Text' that always succeeds+    | FromJSONKeyTextParser !(Text -> Parser a)+      -- ^ conversion from 'Text' that may fail+    | FromJSONKeyValue !(Value -> Parser a)+      -- ^ conversion for non-textual keys++-- | Only law abiding up to interpretation+instance Functor FromJSONKeyFunction where+    fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')+    fmap h (FromJSONKeyText f)            = FromJSONKeyText (h . f)+    fmap h (FromJSONKeyTextParser f)      = FromJSONKeyTextParser (fmap h . f)+    fmap h (FromJSONKeyValue f)           = FromJSONKeyValue (fmap h . f)++-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This+-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be+-- compatible with 'Text' i.e. hash values should be equal for wrapped values as well.+-- This property will always be maintained if the 'Hashable' and 'Eq' instances+-- are derived with generalized newtype deriving.+-- compatible with 'Text' i.e. hash values be equal for wrapped values as well.+--+-- On pre GHC 7.8 this is unconstrainted function.+fromJSONKeyCoerce ::+#if HAS_COERCIBLE+    Coercible Text a =>+#endif+    FromJSONKeyFunction a+fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText++-- | Semantically the same as @coerceFromJSONKeyFunction = fmap coerce = coerce@.+--+-- See note on 'fromJSONKeyCoerce'.+coerceFromJSONKeyFunction ::+#if HAS_COERCIBLE+    Coercible a b =>+#endif+    FromJSONKeyFunction a -> FromJSONKeyFunction b+#if HAS_COERCIBLE+coerceFromJSONKeyFunction = coerce+#else+coerceFromJSONKeyFunction (FromJSONKeyCoerce CoerceText) = FromJSONKeyCoerce CoerceText+coerceFromJSONKeyFunction (FromJSONKeyText f)            = FromJSONKeyText (coerce' . f)+coerceFromJSONKeyFunction (FromJSONKeyTextParser f)      = FromJSONKeyTextParser (fmap coerce' . f)+coerceFromJSONKeyFunction (FromJSONKeyValue f)           = FromJSONKeyValue (fmap coerce' . f)+#endif++{-# RULES+  "FromJSONKeyCoerce: fmap id"     forall (x :: FromJSONKeyFunction a).+                                   fmap id x = x+  #-}+#if HAS_COERCIBLE+{-# RULES+  "FromJSONKeyCoerce: fmap coerce" forall x .+                                   fmap coerce x = coerceFromJSONKeyFunction x+  #-}+#endif++-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.+mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b+mapFromJSONKeyFunction = fmap++-------------------------------------------------------------------------------+-- Functions needed for documentation+-------------------------------------------------------------------------------++-- | Fail parsing due to a type mismatch, with a descriptive message.+--+-- Example usage:+--+-- @+-- instance FromJSON Coord where+--   parseJSON ('Object' v) = {- type matches, life is good -}+--   parseJSON wat        = 'typeMismatch' \"Coord\" wat+-- @+typeMismatch :: String -- ^ The name of the type you are trying to parse.+             -> Value  -- ^ The actual value encountered.+             -> Parser a+typeMismatch expected actual =+    fail $ "expected " ++ expected ++ ", encountered " ++ name+  where+    name = case actual of+             Object _ -> "Object"+             Array _  -> "Array"+             String _ -> "String"+             Number _ -> "Number"+             Bool _   -> "Boolean"+             Null     -> "Null"++-------------------------------------------------------------------------------+-- Lifings of FromJSON and ToJSON to unary and binary type constructors+-------------------------------------------------------------------------------++-- | Lifting of the 'FromJSON' class to unary type constructors.+--+-- Instead of manually writing your 'FromJSON1' instance, there are two options+-- to do it automatically:+--+-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an+-- instance at compile time. The generated instance is optimized for your type+-- so will probably be more efficient than the following two options:+--+-- * The compiler can provide a default generic implementation for+-- 'liftParseJSON'.+--+-- To use the second, simply add a @deriving 'Generic1'@ clause to your+-- datatype and declare a 'FromJSON1' instance for your datatype without giving+-- a definition for 'liftParseJSON'.+--+-- For example:+--+-- @+-- {-\# LANGUAGE DeriveGeneric \#-}+--+-- import "GHC.Generics"+--+-- data Pair a b = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'+--+-- instance FromJSON a => FromJSON1 (Pair a)+-- @+--+-- If @DefaultSignatures@ doesn't give exactly the results you want,+-- you can customize the generic decoding with only a tiny amount of+-- effort, using 'genericLiftParseJSON' with your preferred 'Options':+--+-- @+-- instance FromJSON a => FromJSON1 (Pair a) where+--     liftParseJSON = 'genericLiftParseJSON' 'defaultOptions'+-- @+class FromJSON1 f where+    liftParseJSON :: (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)++    default liftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f))+                          => (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)+    liftParseJSON = genericLiftParseJSON defaultOptions++    liftParseJSONList :: (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser [f a]+    liftParseJSONList f g v = listParser (liftParseJSON f g) v++-- | Lift the standard 'parseJSON' function through the type constructor.+parseJSON1 :: (FromJSON1 f, FromJSON a) => Value -> Parser (f a)+parseJSON1 = liftParseJSON parseJSON parseJSONList+{-# INLINE parseJSON1 #-}++-- | Lifting of the 'FromJSON' class to binary type constructors.+--+-- Instead of manually writing your 'FromJSON2' instance, "Data.Aeson.TH"+-- provides Template Haskell functions which will derive an instance at compile time.++-- The compiler cannot provide a default generic implementation for 'liftParseJSON2',+-- unlike 'parseJSON' and 'liftParseJSON'.+class FromJSON2 f where+    liftParseJSON2+        :: (Value -> Parser a)+        -> (Value -> Parser [a])+        -> (Value -> Parser b)+        -> (Value -> Parser [b])+        -> Value -> Parser (f a b)+    liftParseJSONList2+        :: (Value -> Parser a)+        -> (Value -> Parser [a])+        -> (Value -> Parser b)+        -> (Value -> Parser [b])+        -> Value -> Parser [f a b]+    liftParseJSONList2 fa ga fb gb v = case v of+        Array vals -> fmap V.toList (V.mapM (liftParseJSON2 fa ga fb gb) vals)+        _ -> typeMismatch "[a]" v++-- | Lift the standard 'parseJSON' function through the type constructor.+parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser (f a b)+parseJSON2 = liftParseJSON2 parseJSON parseJSONList parseJSON parseJSONList+{-# INLINE parseJSON2 #-}++-------------------------------------------------------------------------------+-- List functions+-------------------------------------------------------------------------------++-- | Helper function to use with 'liftParseJSON'. See 'Data.Aeson.ToJSON.listEncoding'.+listParser :: (Value -> Parser a) -> Value -> Parser [a]+listParser f (Array xs) = fmap V.toList (V.mapM f xs)+listParser _ v          = typeMismatch "[a]" v+{-# INLINE listParser #-}++-------------------------------------------------------------------------------+-- [] instances+-------------------------------------------------------------------------------++instance FromJSON1 [] where+    liftParseJSON _ p' = p'+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON [a] where+    parseJSON = parseJSON1++-------------------------------------------------------------------------------+-- Functions+-------------------------------------------------------------------------------++-- | @withObject expected f value@ applies @f@ to the 'Object' when @value@ is an @Object@+--   and fails using @'typeMismatch' expected@ otherwise.+withObject :: String -> (Object -> Parser a) -> Value -> Parser a+withObject _        f (Object obj) = f obj+withObject expected _ v            = typeMismatch expected v+{-# INLINE withObject #-}++-- | @withText expected f value@ applies @f@ to the 'Text' when @value@ is a @String@+--   and fails using @'typeMismatch' expected@ otherwise.+withText :: String -> (Text -> Parser a) -> Value -> Parser a+withText _        f (String txt) = f txt+withText expected _ v            = typeMismatch expected v+{-# INLINE withText #-}++-- | @withArray expected f value@ applies @f@ to the 'Array' when @value@ is an @Array@+--   and fails using @'typeMismatch' expected@ otherwise.+withArray :: String -> (Array -> Parser a) -> Value -> Parser a+withArray _        f (Array arr) = f arr+withArray expected _ v           = typeMismatch expected v+{-# INLINE withArray #-}++-- | @withNumber expected f value@ applies @f@ to the 'Number' when @value@ is a 'Number'.+--   and fails using @'typeMismatch' expected@ otherwise.+withNumber :: String -> (Number -> Parser a) -> Value -> Parser a+withNumber expected f = withScientific expected (f . scientificToNumber)+{-# INLINE withNumber #-}+{-# DEPRECATED withNumber "Use withScientific instead" #-}++-- | @withScientific expected f value@ applies @f@ to the 'Scientific' number when @value@ is a 'Number'.+--   and fails using @'typeMismatch' expected@ otherwise.+withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a+withScientific _        f (Number scientific) = f scientific+withScientific expected _ v                   = typeMismatch expected v+{-# INLINE withScientific #-}++-- | @withBool expected f value@ applies @f@ to the 'Bool' when @value@ is a @Bool@+--   and fails using @'typeMismatch' expected@ otherwise.+withBool :: String -> (Bool -> Parser a) -> Value -> Parser a+withBool _        f (Bool arr) = f arr+withBool expected _ v          = typeMismatch expected v+{-# INLINE withBool #-}++-- | Convert a value from JSON, failing if the types do not match.+fromJSON :: (FromJSON a) => Value -> Result a+fromJSON = parse parseJSON+{-# INLINE fromJSON #-}++-- | Convert a value from JSON, failing if the types do not match.+ifromJSON :: (FromJSON a) => Value -> IResult a+ifromJSON = iparse parseJSON+{-# INLINE ifromJSON #-}++-- | Retrieve the value associated with the given key of an 'Object'.+-- The result is 'empty' if the key is not present or the value cannot+-- be converted to the desired type.+--+-- This accessor is appropriate if the key and value /must/ be present+-- in an object for it to be valid.  If the key and value are+-- optional, use '.:?' instead.+(.:) :: (FromJSON a) => Object -> Text -> Parser a+obj .: key = case H.lookup key obj of+               Nothing -> fail $ "key " ++ show key ++ " not present"+               Just v  -> parseJSON v <?> Key key+{-# INLINE (.:) #-}++-- | Retrieve the value associated with the given key of an 'Object'.  The+-- result is 'Nothing' if the key is not present or value is 'Null', or 'empty'+-- if the value cannot be converted to the desired type.+--+-- This accessor is most useful if the key and value can be absent+-- from an object without affecting its validity.  If the key and+-- value are mandatory, use '.:' instead.+(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)+obj .:? key = case H.lookup key obj of+               Nothing -> pure Nothing+               Just v  -> parseJSON v <?> Key key+{-# INLINE (.:?) #-}++-- | Like '.:?', but the resulting parser will fail,+-- if the key is present but is 'Null'.+(.:!) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)+obj .:! key = case H.lookup key obj of+               Nothing -> pure Nothing+               Just v  -> Just <$> parseJSON v <?> Key key+{-# INLINE (.:!) #-}++-- | Helper for use in combination with '.:?' to provide default+-- values for optional JSON object fields.+--+-- This combinator is most useful if the key and value can be absent+-- from an object without affecting its validity and we know a default+-- value to assign in that case.  If the key and value are mandatory,+-- use '.:' instead.+--+-- Example usage:+--+-- @ v1 <- o '.:?' \"opt_field_with_dfl\" .!= \"default_val\"+-- v2 <- o '.:'  \"mandatory_field\"+-- v3 <- o '.:?' \"opt_field2\"+-- @+(.!=) :: Parser (Maybe a) -> a -> Parser a+pmval .!= val = fromMaybe val <$> pmval+{-# INLINE (.!=) #-}++--------------------------------------------------------------------------------+-- Generic parseJSON+-------------------------------------------------------------------------------++instance OVERLAPPABLE_ (GFromJSON arity a) => GFromJSON arity (M1 i c a) where+    -- Meta-information, which is not handled elsewhere, is just added to the+    -- parsed value:+    gParseJSON opts fargs = fmap M1 . gParseJSON opts fargs++instance (FromJSON a) => GFromJSON arity (K1 i a) where+    -- Constant values are decoded using their FromJSON instance:+    gParseJSON _opts _ = fmap K1 . parseJSON++instance GFromJSON One Par1 where+    -- Direct occurrences of the last type parameter are decoded with the+    -- function passed in as an argument:+    gParseJSON _opts (From1Args pj _) = fmap Par1 . pj++instance (FromJSON1 f) => GFromJSON One (Rec1 f) where+    -- Recursive occurrences of the last type parameter are decoded using their+    -- FromJSON1 instance:+    gParseJSON _opts (From1Args pj pjl) = fmap Rec1 . liftParseJSON pj pjl++instance GFromJSON arity U1 where+    -- Empty constructors are expected to be encoded as an empty array:+    gParseJSON _opts _ v+        | isEmptyArray v = pure U1+        | otherwise      = typeMismatch "unit constructor (U1)" v++instance (ConsFromJSON arity a) => GFromJSON arity (C1 c a) where+    -- Constructors need to be decoded differently depending on whether they're+    -- a record or not. This distinction is made by consParseJSON:+    gParseJSON opts fargs = fmap M1 . consParseJSON opts fargs++instance ( FromProduct arity a, FromProduct arity b+         , ProductSize       a, ProductSize       b+         ) => GFromJSON arity (a :*: b) where+    -- Products are expected to be encoded to an array. Here we check whether we+    -- got an array of the same size as the product, then parse each of the+    -- product's elements using parseProduct:+    gParseJSON opts fargs = withArray "product (:*:)" $ \arr ->+      let lenArray = V.length arr+          lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)+                       productSize in+      if lenArray == lenProduct+      then parseProduct opts fargs arr 0 lenProduct+      else fail $ "When expecting a product of " ++ show lenProduct +++                  " values, encountered an Array of " ++ show lenArray +++                  " elements instead"++instance ( AllNullary         (a :+: b) allNullary+         , ParseSum     arity (a :+: b) allNullary+         ) => GFromJSON arity (a :+: b) where+    -- If all constructors of a sum datatype are nullary and the+    -- 'allNullaryToStringTag' option is set they are expected to be+    -- encoded as strings.  This distinction is made by 'parseSum':+    gParseJSON opts fargs =+      (unTagged :: Tagged allNullary (Parser ((a :+: b) d)) ->+                                     Parser ((a :+: b) d))+                 . parseSum opts fargs++instance (FromJSON1 f, GFromJSON One g) => GFromJSON One (f :.: g) where+    -- If an occurrence of the last type parameter is nested inside two+    -- composed types, it is decoded by using the outermost type's FromJSON1+    -- instance to generically decode the innermost type:+    gParseJSON opts fargs =+      let gpj = gParseJSON opts fargs in+      fmap Comp1 . liftParseJSON gpj (listParser gpj)++--------------------------------------------------------------------------------++class ParseSum arity f allNullary where+    parseSum :: Options -> FromArgs arity a+             -> Value -> Tagged allNullary (Parser (f a))++instance ( SumFromString           (a :+: b)+         , FromPair          arity (a :+: b)+         , FromTaggedObject  arity (a :+: b)+         , FromUntaggedValue arity (a :+: b)+         ) => ParseSum       arity (a :+: b) True where+    parseSum opts fargs+        | allNullaryToStringTag opts = Tagged . parseAllNullarySum    opts+        | otherwise                  = Tagged . parseNonAllNullarySum opts fargs++instance ( FromPair          arity (a :+: b)+         , FromTaggedObject  arity (a :+: b)+         , FromUntaggedValue arity (a :+: b)+         ) => ParseSum       arity (a :+: b) False where+    parseSum opts fargs = Tagged . parseNonAllNullarySum opts fargs++--------------------------------------------------------------------------------++parseAllNullarySum :: SumFromString f => Options -> Value -> Parser (f a)+parseAllNullarySum opts = withText "Text" $ \key ->+                            maybe (notFound key) return $+                              parseSumFromString opts key++class SumFromString f where+    parseSumFromString :: Options -> Text -> Maybe (f a)++instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where+    parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>+                                  (R1 <$> parseSumFromString opts key)++instance (Constructor c) => SumFromString (C1 c U1) where+    parseSumFromString opts key | key == name = Just $ M1 U1+                                | otherwise   = Nothing+        where+          name = pack $ constructorTagModifier opts $+                          conName (undefined :: t c U1 p)++--------------------------------------------------------------------------------++parseNonAllNullarySum :: ( FromPair          arity (a :+: b)+                         , FromTaggedObject  arity (a :+: b)+                         , FromUntaggedValue arity (a :+: b)+                         ) => Options -> FromArgs arity c+                           -> Value -> Parser ((a :+: b) c)+parseNonAllNullarySum opts fargs =+    case sumEncoding opts of+      TaggedObject{..} ->+          withObject "Object" $ \obj -> do+            tag <- obj .: pack tagFieldName+            fromMaybe (notFound tag) $+              parseFromTaggedObject opts fargs contentsFieldName obj tag++      ObjectWithSingleField ->+          withObject "Object" $ \obj ->+            case H.toList obj of+              [pair@(tag, _)] -> fromMaybe (notFound tag) $+                                   parsePair opts fargs pair+              _ -> fail "Object doesn't have a single field"++      TwoElemArray ->+          withArray "Array" $ \arr ->+            if V.length arr == 2+            then case V.unsafeIndex arr 0 of+                   String tag -> fromMaybe (notFound tag) $+                                   parsePair opts fargs (tag, V.unsafeIndex arr 1)+                   _ -> fail "First element is not a String"+            else fail "Array doesn't have 2 elements"++      UntaggedValue -> parseUntaggedValue opts fargs++--------------------------------------------------------------------------------++class FromTaggedObject arity f where+    parseFromTaggedObject :: Options -> FromArgs arity a+                          -> String -> Object+                          -> Text -> Maybe (Parser (f a))++instance ( FromTaggedObject arity a, FromTaggedObject arity b) =>+    FromTaggedObject arity (a :+: b) where+        parseFromTaggedObject opts fargs contentsFieldName obj tag =+            (fmap L1 <$> parseFromTaggedObject opts fargs contentsFieldName obj tag) <|>+            (fmap R1 <$> parseFromTaggedObject opts fargs contentsFieldName obj tag)++instance ( FromTaggedObject' arity f+         , Constructor c+         ) => FromTaggedObject arity (C1 c f) where+    parseFromTaggedObject opts fargs contentsFieldName obj tag+        | tag == name = Just $ M1 <$> parseFromTaggedObject'+                                        opts fargs contentsFieldName obj+        | otherwise = Nothing+        where+          name = pack $ constructorTagModifier opts $+                          conName (undefined :: t c f p)++--------------------------------------------------------------------------------++class FromTaggedObject' arity f where+    parseFromTaggedObject' :: Options -> FromArgs arity a -> String+                           -> Object -> Parser (f a)++class FromTaggedObject'' arity f isRecord where+    parseFromTaggedObject'' :: Options -> FromArgs arity a -> String+                            -> Object -> Tagged isRecord (Parser (f a))++instance ( IsRecord                   f isRecord+         , FromTaggedObject''   arity f isRecord+         ) => FromTaggedObject' arity f where+    parseFromTaggedObject' opts fargs contentsFieldName =+        (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a)) .+        parseFromTaggedObject'' opts fargs contentsFieldName++instance (FromRecord arity f) => FromTaggedObject'' arity f True where+    parseFromTaggedObject'' opts fargs _ =+      Tagged . parseRecord opts fargs Nothing++instance (GFromJSON arity f) => FromTaggedObject'' arity f False where+    parseFromTaggedObject'' opts fargs contentsFieldName = Tagged .+      (gParseJSON opts fargs <=< (.: pack contentsFieldName))++instance OVERLAPPING_ FromTaggedObject'' arity U1 False where+    parseFromTaggedObject'' _ _ _ _ = Tagged (pure U1)++--------------------------------------------------------------------------------++class ConsFromJSON arity f where+    consParseJSON  :: Options -> FromArgs arity a+                   -> Value -> Parser (f a)++class ConsFromJSON' arity f isRecord where+    consParseJSON' :: Options -> FromArgs arity a+                   -> Maybe Text -- ^ A dummy label+                                 --   (Nothing to use proper label)+                   -> Value -> Tagged isRecord (Parser (f a))++instance ( IsRecord            f isRecord+         , ConsFromJSON' arity f isRecord+         ) => ConsFromJSON arity f where+    consParseJSON opts fargs v = let+      (v2,lab) = case (unwrapUnaryRecords opts,isUnary (undefined :: f a)) of+                       -- use a dummy object with a dummy label+        (True,True) -> (object [(pack "dummy",v)], Just $ pack "dummy")+        _ ->(v,Nothing)+      in (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a))+                       $ consParseJSON' opts fargs lab v2+++instance (FromRecord arity f) => ConsFromJSON' arity f True where+    consParseJSON' opts fargs mlab = Tagged . withObject "record (:*:)"+                                        (parseRecord opts fargs mlab)++instance (GFromJSON arity f) => ConsFromJSON' arity f False where+    consParseJSON' opts fargs _ = Tagged . gParseJSON opts fargs++--------------------------------------------------------------------------------++class FromRecord arity f where+    parseRecord :: Options -> FromArgs arity a+                -> Maybe Text -- ^ A dummy label+                              --   (Nothing to use proper label)+                -> Object -> Parser (f a)++instance ( FromRecord arity a+         , FromRecord arity b+         ) => FromRecord arity (a :*: b) where+    parseRecord opts fargs _ obj =+      (:*:) <$> parseRecord opts fargs Nothing obj+            <*> parseRecord opts fargs Nothing obj++instance ( Selector s+         , GFromJSON arity a+         ) => FromRecord arity (S1 s a) where+    parseRecord opts fargs lab =+      (<?> Key label) . gParseJSON opts fargs <=< (.: label)+        where+          label = fromMaybe defLabel lab+          defLabel = pack . fieldLabelModifier opts $+                       selName (undefined :: t s a p)++instance OVERLAPPING_ (Selector s, FromJSON a) =>+  FromRecord arity (S1 s (K1 i (Maybe a))) where+    parseRecord _ _ (Just lab) obj = (M1 . K1) <$> obj .:? lab+    parseRecord opts _ Nothing obj = (M1 . K1) <$> obj .:? pack label+        where+          label = fieldLabelModifier opts $+                    selName (undefined :: t s (K1 i (Maybe a)) p)++--------------------------------------------------------------------------------++class FromProduct arity f where+    parseProduct :: Options -> FromArgs arity a+                 -> Array -> Int -> Int+                 -> Parser (f a)++instance ( FromProduct    arity a+         , FromProduct    arity b+         ) => FromProduct arity (a :*: b) where+    parseProduct opts fargs arr ix len =+        (:*:) <$> parseProduct opts fargs arr ix  lenL+              <*> parseProduct opts fargs arr ixR lenR+        where+          lenL = len `unsafeShiftR` 1+          ixR  = ix + lenL+          lenR = len - lenL++instance (GFromJSON arity a) => FromProduct arity (S1 s a) where+    parseProduct opts fargs arr ix _ =+      gParseJSON opts fargs $ V.unsafeIndex arr ix++--------------------------------------------------------------------------------++class FromPair arity f where+    parsePair :: Options -> FromArgs arity a+              -> Pair -> Maybe (Parser (f a))++instance ( FromPair arity a+         , FromPair arity b+         ) => FromPair arity (a :+: b) where+    parsePair opts fargs pair = (fmap L1 <$> parsePair opts fargs pair) <|>+                                (fmap R1 <$> parsePair opts fargs pair)++instance ( Constructor c+         , GFromJSON    arity a+         , ConsFromJSON arity a+         ) => FromPair arity (C1 c a) where+    parsePair opts fargs (tag, value)+        | tag == tag' = Just $ gParseJSON opts fargs value+        | otherwise   = Nothing+        where+          tag' = pack $ constructorTagModifier opts $+                          conName (undefined :: t c a p)++--------------------------------------------------------------------------------++class FromUntaggedValue arity f where+    parseUntaggedValue :: Options -> FromArgs arity a+                       -> Value -> Parser (f a)++instance+    ( FromUntaggedValue    arity a+    , FromUntaggedValue    arity b+    ) => FromUntaggedValue arity (a :+: b)+  where+    parseUntaggedValue opts fargs value =+        L1 <$> parseUntaggedValue opts fargs value <|>+        R1 <$> parseUntaggedValue opts fargs value++instance OVERLAPPABLE_+    ( GFromJSON            arity a+    , ConsFromJSON         arity a+    ) => FromUntaggedValue arity (C1 c a)+  where+    parseUntaggedValue = gParseJSON++instance OVERLAPPING_+    ( Constructor c )+    => FromUntaggedValue arity (C1 c U1)+  where+    parseUntaggedValue opts _ (String s)+        | s == pack (constructorTagModifier opts (conName (undefined :: t c U1 p))) =+            pure $ M1 U1+        | otherwise =+            fail $ "Invalid tag: " ++ unpack s+    parseUntaggedValue _ _ v = typeMismatch (conName (undefined :: t c U1 p)) v+++--------------------------------------------------------------------------------++notFound :: Text -> Parser a+notFound key = fail $ "The key \"" ++ unpack key ++ "\" was not found"+{-# INLINE notFound #-}++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++-------------------------------------------------------------------------------+-- base+-------------------------------------------------------------------------------+++instance FromJSON2 Const where+    liftParseJSON2 p _ _ _ = fmap Const . p+    {-# INLINE liftParseJSON2 #-}++instance FromJSON a => FromJSON1 (Const a) where+    liftParseJSON _ _ = fmap Const . parseJSON+    {-# INLINE liftParseJSON #-}++instance FromJSON a => FromJSON (Const a b) where+    {-# INLINE parseJSON #-}+    parseJSON = fmap Const . parseJSON+++instance FromJSON1 Maybe where+    liftParseJSON _ _ Null = pure Nothing+    liftParseJSON p _ a    = Just <$> p a+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON (Maybe a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++++instance FromJSON2 Either where+    liftParseJSON2 pA _ pB _ (Object (H.toList -> [(key, value)]))+        | key == left  = Left  <$> pA value <?> Key left+        | key == right = Right <$> pB value <?> Key right+      where+        left, right :: Text+        left  = "Left"+        right = "Right"++    liftParseJSON2 _ _ _ _ _ = fail $+        "expected an object with a single property " +++        "where the property key should be either " +++        "\"Left\" or \"Right\""+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a) => FromJSON1 (Either a) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}++++instance FromJSON Bool where+    parseJSON = withBool "Bool" pure+    {-# INLINE parseJSON #-}++instance FromJSONKey Bool where+    fromJSONKey = FromJSONKeyTextParser $ \t -> case t of+        "true"  -> pure True+        "false" -> pure False+        _       -> fail $ "Cannot parse key into Bool: " ++ T.unpack t++instance FromJSON Ordering where+  parseJSON = withText "Ordering" $ \s ->+    case s of+      "LT" -> return LT+      "EQ" -> return EQ+      "GT" -> return GT+      _ -> fail "Parsing Ordering value failed: expected \"LT\", \"EQ\", or \"GT\""++instance FromJSON () where+    parseJSON = withArray "()" $ \v ->+                  if V.null v+                    then pure ()+                    else fail "Expected an empty array"+    {-# INLINE parseJSON #-}++instance FromJSON Char where+    parseJSON = withText "Char" $ \t ->+                  if T.compareLength t 1 == EQ+                    then pure $ T.head t+                    else fail "Expected a string of length 1"+    {-# INLINE parseJSON #-}++    parseJSONList = withText "String" $ pure . T.unpack+    {-# INLINE parseJSONList #-}++instance FromJSON Double where+    parseJSON = parseRealFloat "Double"+    {-# INLINE parseJSON #-}++instance FromJSONKey Double where+    fromJSONKey = FromJSONKeyTextParser $ \t -> case t of+        "NaN"       -> pure (0/0)+        "Infinity"  -> pure (1/0)+        "-Infinity" -> pure (negate 1/0)+        _           -> Scientific.toRealFloat <$> parseScientificText t++instance FromJSON Number where+    parseJSON (Number s) = pure $ scientificToNumber s+    parseJSON Null       = pure (D (0/0))+    parseJSON v          = typeMismatch "Number" v+    {-# INLINE parseJSON #-}++instance FromJSON Float where+    parseJSON = parseRealFloat "Float"+    {-# INLINE parseJSON #-}++instance FromJSONKey Float where+    fromJSONKey = FromJSONKeyTextParser $ \t -> case t of+        "NaN"       -> pure (0/0)+        "Infinity"  -> pure (1/0)+        "-Infinity" -> pure (negate 1/0)+        _           -> Scientific.toRealFloat <$> parseScientificText t++instance (FromJSON a, Integral a) => FromJSON (Ratio a) where+    parseJSON = withObject "Rational" $ \obj ->+                  (%) <$> obj .: "numerator"+                      <*> obj .: "denominator"+    {-# INLINE parseJSON #-}++-- | /WARNING:/ Only parse fixed-precision numbers from trusted input+-- since an attacker could easily fill up the memory of the target+-- system by specifying a scientific number with a big exponent like+-- @1e1000000000@.+instance HasResolution a => FromJSON (Fixed a) where+    parseJSON = withScientific "Fixed" $ pure . realToFrac+    {-# INLINE parseJSON #-}++instance FromJSON Int where+    parseJSON = parseBoundedIntegral "Int"+    {-# INLINE parseJSON #-}++instance FromJSONKey Int where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int"++-- | /WARNING:/ Only parse Integers from trusted input since an+-- attacker could easily fill up the memory of the target system by+-- specifying a scientific number with a big exponent like+-- @1e1000000000@.+instance FromJSON Integer where+    parseJSON = parseIntegral "Integer"+    {-# INLINE parseJSON #-}++instance FromJSONKey Integer where+    fromJSONKey = FromJSONKeyTextParser $ parseIntegralText "Integer"++instance FromJSON Natural where+    parseJSON = withScientific "Natural" $ \s ->+      if Scientific.coefficient s < 0+        then fail $ "Expected a Natural number but got the negative number: " <> show s+        else pure $ truncate s++instance FromJSONKey Natural where+    fromJSONKey = FromJSONKeyTextParser $ \t -> parseScientificText t >>= \s ->+      if Scientific.coefficient s < 0+        then fail $ "Expected a Natural number but got the negative number: " <> show s+        else pure $ truncate s++instance FromJSON Int8 where+    parseJSON = parseBoundedIntegral "Int8"+    {-# INLINE parseJSON #-}++instance FromJSONKey Int8 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int8"++instance FromJSON Int16 where+    parseJSON = parseBoundedIntegral "Int16"+    {-# INLINE parseJSON #-}++instance FromJSONKey Int16 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int16"++instance FromJSON Int32 where+    parseJSON = parseBoundedIntegral "Int32"+    {-# INLINE parseJSON #-}++instance FromJSONKey Int32 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int32"++instance FromJSON Int64 where+    parseJSON = parseBoundedIntegral "Int64"+    {-# INLINE parseJSON #-}++instance FromJSONKey Int64 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int64"++instance FromJSON Word where+    parseJSON = parseBoundedIntegral "Word"+    {-# INLINE parseJSON #-}++instance FromJSONKey Word where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word"++instance FromJSON Word8 where+    parseJSON = parseBoundedIntegral "Word8"+    {-# INLINE parseJSON #-}++instance FromJSONKey Word8 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word8"++instance FromJSON Word16 where+    parseJSON = parseBoundedIntegral "Word16"+    {-# INLINE parseJSON #-}++instance FromJSONKey Word16 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word16"++instance FromJSON Word32 where+    parseJSON = parseBoundedIntegral "Word32"+    {-# INLINE parseJSON #-}++instance FromJSONKey Word32 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word32"++instance FromJSON Word64 where+    parseJSON = parseBoundedIntegral "Word64"+    {-# INLINE parseJSON #-}++instance FromJSONKey Word64 where+    fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word64"+++instance FromJSON Text where+    parseJSON = withText "Text" pure+    {-# INLINE parseJSON #-}++instance FromJSONKey Text where+    fromJSONKey = fromJSONKeyCoerce+++instance FromJSON LT.Text where+    parseJSON = withText "Lazy Text" $ pure . LT.fromStrict+    {-# INLINE parseJSON #-}++instance FromJSONKey LT.Text where+    fromJSONKey = FromJSONKeyText LT.fromStrict+++instance FromJSON Version where+    parseJSON = withText "Version" parseVersionText+    {-# INLINE parseJSON #-}++instance FromJSONKey Version where+    fromJSONKey = FromJSONKeyTextParser parseVersionText++parseVersionText :: Text -> Parser Version+parseVersionText = go . readP_to_S parseVersion . unpack+  where+    go [(v,[])] = return v+    go (_ : xs) = go xs+    go _        = fail "could not parse Version"++-------------------------------------------------------------------------------+-- semigroups NonEmpty+-------------------------------------------------------------------------------++instance FromJSON1 NonEmpty where+    liftParseJSON p _ = withArray "NonEmpty a" $+        (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList+      where+        ne []     = fail "Expected a NonEmpty but got an empty list"+        ne (x:xs) = pure (x :| xs)+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON (NonEmpty a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- scientific+-------------------------------------------------------------------------------++instance FromJSON Scientific where+    parseJSON = withScientific "Scientific" pure+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- DList+-------------------------------------------------------------------------------++instance FromJSON1 DList.DList where+    liftParseJSON p _ = withArray "DList a" $+      fmap DList.fromList .+      Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON (DList.DList a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- tranformers - Functors+-------------------------------------------------------------------------------++instance FromJSON1 Identity where+    liftParseJSON p _ a = Identity <$> p a+    {-# INLINE liftParseJSON #-}++    liftParseJSONList _ p a = fmap Identity <$> p a+    {-# INLINE liftParseJSONList #-}++instance (FromJSON a) => FromJSON (Identity a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++    parseJSONList = liftParseJSONList parseJSON parseJSONList+    {-# INLINE parseJSONList #-}++instance (FromJSONKey a, FromJSON a) => FromJSONKey (Identity a) where+    fromJSONKey = coerceFromJSONKeyFunction (fromJSONKey :: FromJSONKeyFunction a)+    fromJSONKeyList = coerceFromJSONKeyFunction (fromJSONKeyList :: FromJSONKeyFunction [a])+++instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Compose f g) where+    liftParseJSON p pl a = Compose <$> liftParseJSON g gl a+      where+        g  = liftParseJSON p pl+        gl = liftParseJSONList p pl+    {-# INLINE liftParseJSON #-}++    liftParseJSONList p pl a = map Compose <$> liftParseJSONList g gl a+      where+        g  = liftParseJSON p pl+        gl = liftParseJSONList p pl+    {-# INLINE liftParseJSONList #-}++instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Compose f g a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++    parseJSONList = liftParseJSONList parseJSON parseJSONList+    {-# INLINE parseJSONList #-}+++instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Product f g) where+    liftParseJSON p pl a = uncurry Pair <$> liftParseJSON2 px pxl py pyl a+      where+        px  = liftParseJSON p pl+        pxl = liftParseJSONList p pl+        py  = liftParseJSON p pl+        pyl = liftParseJSONList p pl+    {-# INLINE liftParseJSON #-}++instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Product f g a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Sum f g) where+    liftParseJSON p pl (Object (H.toList -> [(key, value)]))+        | key == inl = InL <$> liftParseJSON p pl value <?> Key inl+        | key == inr = InR <$> liftParseJSON p pl value <?> Key inl+      where+        inl, inr :: Text+        inl = "InL"+        inr = "InR"++    liftParseJSON _ _ _ = fail $+        "expected an object with a single property " +++        "where the property key should be either " +++        "\"InL\" or \"InR\""+    {-# INLINE liftParseJSON #-}++instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Sum f g a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- containers+-------------------------------------------------------------------------------++instance FromJSON1 Seq.Seq where+    liftParseJSON p _ = withArray "Seq a" $+      fmap Seq.fromList .+      Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON (Seq.Seq a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++instance (Ord a, FromJSON a) => FromJSON (Set.Set a) where+    parseJSON = fmap Set.fromList . parseJSON+    {-# INLINE parseJSON #-}+++instance FromJSON IntSet.IntSet where+    parseJSON = fmap IntSet.fromList . parseJSON+    {-# INLINE parseJSON #-}+++instance FromJSON1 IntMap.IntMap where+    liftParseJSON p pl = fmap IntMap.fromList . liftParseJSON p' pl'+      where+        p'  = liftParseJSON2     parseJSON parseJSONList p pl+        pl' = liftParseJSONList2 parseJSON parseJSONList p pl+    {-# INLINE liftParseJSON #-}++instance FromJSON a => FromJSON (IntMap.IntMap a) where+    parseJSON = fmap IntMap.fromList . parseJSON+    {-# INLINE parseJSON #-}+++instance (FromJSONKey k, Ord k) => FromJSON1 (M.Map k) where+    liftParseJSON p _ = case fromJSONKey of+        FromJSONKeyCoerce _-> withObject "Map k v" $+            fmap (H.foldrWithKey (M.insert . unsafeCoerce) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)+        FromJSONKeyText f -> withObject "Map k v" $+            fmap (H.foldrWithKey (M.insert . f) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)+        FromJSONKeyTextParser f -> withObject "Map k v" $+            H.foldrWithKey (\k v m -> M.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure M.empty)+        FromJSONKeyValue f -> withArray "Map k v" $ \arr ->+            M.fromList <$> (Tr.sequence .+                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)+    {-# INLINE liftParseJSON #-}++instance (FromJSONKey k, Ord k, FromJSON v) => FromJSON (M.Map k v) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++instance FromJSON1 Tree.Tree where+    liftParseJSON p pl = go+      where+        go v = uncurry Tree.Node <$> liftParseJSON2 p pl p' pl' v++        p' = liftParseJSON go (listParser go)+        pl'= liftParseJSONList go (listParser go)++instance (FromJSON v) => FromJSON (Tree.Tree v) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- vector+-------------------------------------------------------------------------------++instance FromJSON1 Vector where+    liftParseJSON p _ = withArray "Vector a" $+        V.mapM (uncurry $ parseIndexedJSON p) . V.indexed+    {-# INLINE liftParseJSON #-}++instance (FromJSON a) => FromJSON (Vector a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++vectorParseJSON :: (FromJSON a, VG.Vector w a) => String -> Value -> Parser (w a)+vectorParseJSON s = withArray s $ fmap V.convert . V.mapM (uncurry $ parseIndexedJSON parseJSON) . V.indexed+{-# INLINE vectorParseJSON #-}++instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where+    parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"++instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where+    parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"+    {-# INLINE parseJSON #-}++instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where+    parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- unordered-containers+-------------------------------------------------------------------------------++instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where+    parseJSON = fmap HashSet.fromList . parseJSON+    {-# INLINE parseJSON #-}+++instance (FromJSONKey k, Eq k, Hashable k) => FromJSON1 (H.HashMap k) where+    liftParseJSON p _ = case fromJSONKey of+        FromJSONKeyCoerce _ -> withObject "HashMap ~Text v" $+            uc . H.traverseWithKey (\k v -> p v <?> Key k)+        FromJSONKeyText f -> withObject "HashMap k v" $+            fmap (mapKey f) . H.traverseWithKey (\k v -> p v <?> Key k)+        FromJSONKeyTextParser f -> withObject "HashMap k v" $+            H.foldrWithKey (\k v m -> H.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure H.empty)+        FromJSONKeyValue f -> withArray "Map k v" $ \arr ->+            H.fromList <$> (Tr.sequence .+                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)+      where+        uc :: Parser (H.HashMap Text v) -> Parser (H.HashMap k v)+        uc = unsafeCoerce++instance (FromJSON v, FromJSONKey k, Eq k, Hashable k) => FromJSON (H.HashMap k v) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- aeson+-------------------------------------------------------------------------------++instance FromJSON Value where+    parseJSON = pure+    {-# INLINE parseJSON #-}++instance FromJSON DotNetTime where+    parseJSON = withText "DotNetTime" $ \t ->+        let (s,m) = T.splitAt (T.length t - 5) t+            t'    = T.concat [s,".",m]+        in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of+             Just d -> pure (DotNetTime d)+             _      -> fail "could not parse .NET time"+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- time+-------------------------------------------------------------------------------++instance FromJSON Day where+    parseJSON = withText "Day" (Time.run Time.day)++instance FromJSONKey Day where+    fromJSONKey = FromJSONKeyTextParser (Time.run Time.day)+++instance FromJSON TimeOfDay where+    parseJSON = withText "TimeOfDay" (Time.run Time.timeOfDay)++instance FromJSONKey TimeOfDay where+    fromJSONKey = FromJSONKeyTextParser (Time.run Time.timeOfDay)+++instance FromJSON LocalTime where+    parseJSON = withText "LocalTime" (Time.run Time.localTime)++instance FromJSONKey LocalTime where+    fromJSONKey = FromJSONKeyTextParser (Time.run Time.localTime)+++instance FromJSON ZonedTime where+    parseJSON = withText "ZonedTime" (Time.run Time.zonedTime)++instance FromJSONKey ZonedTime where+    fromJSONKey = FromJSONKeyTextParser (Time.run Time.zonedTime)+++instance FromJSON UTCTime where+    parseJSON = withText "UTCTime" (Time.run Time.utcTime)++instance FromJSONKey UTCTime where+    fromJSONKey = FromJSONKeyTextParser (Time.run Time.utcTime)+++-- | /WARNING:/ Only parse lengths of time from trusted input+-- since an attacker could easily fill up the memory of the target+-- system by specifying a scientific number with a big exponent like+-- @1e1000000000@.+instance FromJSON NominalDiffTime where+    parseJSON = withScientific "NominalDiffTime" $ pure . realToFrac+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- base Monoid/Semigroup+-------------------------------------------------------------------------------++instance FromJSON1 Dual where+    liftParseJSON p _ = fmap Dual . p+    {-# INLINE liftParseJSON #-}++instance FromJSON a => FromJSON (Dual a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++instance FromJSON1 First where+    liftParseJSON p p' = fmap First . liftParseJSON p p'+    {-# INLINE liftParseJSON #-}++instance FromJSON a => FromJSON (First a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}+++instance FromJSON1 Last where+    liftParseJSON p p' = fmap Last . liftParseJSON p p'+    {-# INLINE liftParseJSON #-}++instance FromJSON a => FromJSON (Last a) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++-------------------------------------------------------------------------------+-- tagged+-------------------------------------------------------------------------------++instance FromJSON (Proxy a) where+    {-# INLINE parseJSON #-}+    parseJSON Null = pure Proxy+    parseJSON v    = typeMismatch "Proxy" v+++instance FromJSON1 (Tagged a) where+    liftParseJSON p _ = fmap Tagged . p+    {-# INLINE liftParseJSON #-}++instance FromJSON b => FromJSON (Tagged a b) where+    parseJSON = parseJSON1+    {-# INLINE parseJSON #-}++instance FromJSONKey b => FromJSONKey (Tagged a b) where+    fromJSONKey = coerceFromJSONKeyFunction (fromJSONKey :: FromJSONKeyFunction b)+    fromJSONKeyList = (fmap . fmap) Tagged fromJSONKeyList++-------------------------------------------------------------------------------+-- Instances for converting from map keys+-------------------------------------------------------------------------------++instance (FromJSON a, FromJSON b) => FromJSONKey (a,b)+instance (FromJSON a, FromJSON b, FromJSON c) => FromJSONKey (a,b,c)+instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSONKey (a,b,c,d)++instance FromJSONKey Char where+    fromJSONKey = FromJSONKeyTextParser $ \t ->+        if T.length t == 1+            then return (T.index t 0)+            else typeMismatch "Expected Char but String didn't contain exactly one character" (String t)+    fromJSONKeyList = FromJSONKeyText T.unpack++instance (FromJSONKey a, FromJSON a) => FromJSONKey [a] where+    fromJSONKey = fromJSONKeyList++-------------------------------------------------------------------------------+-- Tuple instances, see tuple-instances-from.hs+-------------------------------------------------------------------------------++instance FromJSON2 (,) where+    liftParseJSON2 pA _ pB _ = withArray "(a, b)" $ \t ->+        let n = V.length t+        in if n == 2+            then (,)+                <$> parseJSONElemAtIndex pA 0 t+                <*> parseJSONElemAtIndex pB 1 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 2"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a) => FromJSON1 ((,) a) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b) => FromJSON (a, b) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a) => FromJSON2 ((,,) a) where+    liftParseJSON2 pB _ pC _ = withArray "(a, b, c)" $ \t ->+        let n = V.length t+        in if n == 3+            then (,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex pB 1 t+                <*> parseJSONElemAtIndex pC 2 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 3"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b) => FromJSON1 ((,,) a b) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON (a, b, c) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b) => FromJSON2 ((,,,) a b) where+    liftParseJSON2 pC _ pD _ = withArray "(a, b, c, d)" $ \t ->+        let n = V.length t+        in if n == 4+            then (,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex pC 2 t+                <*> parseJSONElemAtIndex pD 3 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 4"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON1 ((,,,) a b c) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSON (a, b, c, d) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON2 ((,,,,) a b c) where+    liftParseJSON2 pD _ pE _ = withArray "(a, b, c, d, e)" $ \t ->+        let n = V.length t+        in if n == 5+            then (,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex pD 3 t+                <*> parseJSONElemAtIndex pE 4 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 5"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSON1 ((,,,,) a b c d) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e) => FromJSON (a, b, c, d, e) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSON2 ((,,,,,) a b c d) where+    liftParseJSON2 pE _ pF _ = withArray "(a, b, c, d, e, f)" $ \t ->+        let n = V.length t+        in if n == 6+            then (,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex pE 4 t+                <*> parseJSONElemAtIndex pF 5 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 6"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e) => FromJSON1 ((,,,,,) a b c d e) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f) => FromJSON (a, b, c, d, e, f) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e) => FromJSON2 ((,,,,,,) a b c d e) where+    liftParseJSON2 pF _ pG _ = withArray "(a, b, c, d, e, f, g)" $ \t ->+        let n = V.length t+        in if n == 7+            then (,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex pF 5 t+                <*> parseJSONElemAtIndex pG 6 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 7"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f) => FromJSON1 ((,,,,,,) a b c d e f) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g) => FromJSON (a, b, c, d, e, f, g) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f) => FromJSON2 ((,,,,,,,) a b c d e f) where+    liftParseJSON2 pG _ pH _ = withArray "(a, b, c, d, e, f, g, h)" $ \t ->+        let n = V.length t+        in if n == 8+            then (,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex pG 6 t+                <*> parseJSONElemAtIndex pH 7 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 8"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g) => FromJSON1 ((,,,,,,,) a b c d e f g) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h) => FromJSON (a, b, c, d, e, f, g, h) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g) => FromJSON2 ((,,,,,,,,) a b c d e f g) where+    liftParseJSON2 pH _ pI _ = withArray "(a, b, c, d, e, f, g, h, i)" $ \t ->+        let n = V.length t+        in if n == 9+            then (,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex pH 7 t+                <*> parseJSONElemAtIndex pI 8 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 9"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h) => FromJSON1 ((,,,,,,,,) a b c d e f g h) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i) => FromJSON (a, b, c, d, e, f, g, h, i) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h) => FromJSON2 ((,,,,,,,,,) a b c d e f g h) where+    liftParseJSON2 pI _ pJ _ = withArray "(a, b, c, d, e, f, g, h, i, j)" $ \t ->+        let n = V.length t+        in if n == 10+            then (,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex pI 8 t+                <*> parseJSONElemAtIndex pJ 9 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 10"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i) => FromJSON1 ((,,,,,,,,,) a b c d e f g h i) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j) => FromJSON (a, b, c, d, e, f, g, h, i, j) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i) => FromJSON2 ((,,,,,,,,,,) a b c d e f g h i) where+    liftParseJSON2 pJ _ pK _ = withArray "(a, b, c, d, e, f, g, h, i, j, k)" $ \t ->+        let n = V.length t+        in if n == 11+            then (,,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex parseJSON 8 t+                <*> parseJSONElemAtIndex pJ 9 t+                <*> parseJSONElemAtIndex pK 10 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 11"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j) => FromJSON1 ((,,,,,,,,,,) a b c d e f g h i j) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k) => FromJSON (a, b, c, d, e, f, g, h, i, j, k) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j) => FromJSON2 ((,,,,,,,,,,,) a b c d e f g h i j) where+    liftParseJSON2 pK _ pL _ = withArray "(a, b, c, d, e, f, g, h, i, j, k, l)" $ \t ->+        let n = V.length t+        in if n == 12+            then (,,,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex parseJSON 8 t+                <*> parseJSONElemAtIndex parseJSON 9 t+                <*> parseJSONElemAtIndex pK 10 t+                <*> parseJSONElemAtIndex pL 11 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 12"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k) => FromJSON1 ((,,,,,,,,,,,) a b c d e f g h i j k) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l) => FromJSON (a, b, c, d, e, f, g, h, i, j, k, l) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k) => FromJSON2 ((,,,,,,,,,,,,) a b c d e f g h i j k) where+    liftParseJSON2 pL _ pM _ = withArray "(a, b, c, d, e, f, g, h, i, j, k, l, m)" $ \t ->+        let n = V.length t+        in if n == 13+            then (,,,,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex parseJSON 8 t+                <*> parseJSONElemAtIndex parseJSON 9 t+                <*> parseJSONElemAtIndex parseJSON 10 t+                <*> parseJSONElemAtIndex pL 11 t+                <*> parseJSONElemAtIndex pM 12 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 13"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l) => FromJSON1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m) => FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l) => FromJSON2 ((,,,,,,,,,,,,,) a b c d e f g h i j k l) where+    liftParseJSON2 pM _ pN _ = withArray "(a, b, c, d, e, f, g, h, i, j, k, l, m, n)" $ \t ->+        let n = V.length t+        in if n == 14+            then (,,,,,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex parseJSON 8 t+                <*> parseJSONElemAtIndex parseJSON 9 t+                <*> parseJSONElemAtIndex parseJSON 10 t+                <*> parseJSONElemAtIndex parseJSON 11 t+                <*> parseJSONElemAtIndex pM 12 t+                <*> parseJSONElemAtIndex pN 13 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 14"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m) => FromJSON1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m, FromJSON n) => FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}+++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m) => FromJSON2 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m) where+    liftParseJSON2 pN _ pO _ = withArray "(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)" $ \t ->+        let n = V.length t+        in if n == 15+            then (,,,,,,,,,,,,,,)+                <$> parseJSONElemAtIndex parseJSON 0 t+                <*> parseJSONElemAtIndex parseJSON 1 t+                <*> parseJSONElemAtIndex parseJSON 2 t+                <*> parseJSONElemAtIndex parseJSON 3 t+                <*> parseJSONElemAtIndex parseJSON 4 t+                <*> parseJSONElemAtIndex parseJSON 5 t+                <*> parseJSONElemAtIndex parseJSON 6 t+                <*> parseJSONElemAtIndex parseJSON 7 t+                <*> parseJSONElemAtIndex parseJSON 8 t+                <*> parseJSONElemAtIndex parseJSON 9 t+                <*> parseJSONElemAtIndex parseJSON 10 t+                <*> parseJSONElemAtIndex parseJSON 11 t+                <*> parseJSONElemAtIndex parseJSON 12 t+                <*> parseJSONElemAtIndex pN 13 t+                <*> parseJSONElemAtIndex pO 14 t+            else fail $ "cannot unpack array of length " ++ show n ++ " into a tuple of length 15"+    {-# INLINE liftParseJSON2 #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m, FromJSON n) => FromJSON1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) where+    liftParseJSON = liftParseJSON2 parseJSON parseJSONList+    {-# INLINE liftParseJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m, FromJSON n, FromJSON o) => FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+    parseJSON = parseJSON2+    {-# INLINE parseJSON #-}
Data/Aeson/Types/Generic.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE CPP, DefaultSignatures, EmptyDataDecls, FlexibleInstances,-    FunctionalDependencies, KindSignatures,-    ScopedTypeVariables, TypeOperators, UndecidableInstances,-    ViewPatterns, NamedFieldPuns, FlexibleContexts, PatternGuards,-    RecordWildCards, DataKinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}  #include "overlapping-compat.h" @@ -17,717 +21,25 @@ -- Stability:   experimental -- Portability: portable ----- Types for working with JSON data.--module Data.Aeson.Types.Generic ( ) where--import Control.Applicative ((<|>))-import Control.Monad ((<=<))-import Control.Monad.ST (ST)-import Data.Aeson.Encode.Builder (emptyArray_)-import Data.Aeson.Encode.Functions (builder)-import Data.Aeson.Types.Instances-import Data.Aeson.Types.Internal-import Data.Bits (unsafeShiftR)-import Data.ByteString.Builder as B-import Data.DList (DList, toList, empty)-import Data.Maybe (fromMaybe)-import Data.Monoid ((<>))-import Data.Text (Text, pack, unpack)-import GHC.Generics-import qualified Data.HashMap.Strict as H-import qualified Data.Vector as V-import qualified Data.Vector.Mutable as VM--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<*>), (<$>), pure)-import Data.Monoid (mempty)-#endif------------------------------------------------------------------------------------- Generic toJSON--instance OVERLAPPABLE_ (GToJSON a) => GToJSON (M1 i c a) where-    -- Meta-information, which is not handled elsewhere, is ignored:-    gToJSON opts = gToJSON opts . unM1--instance (ToJSON a) => GToJSON (K1 i a) where-    -- Constant values are encoded using their ToJSON instance:-    gToJSON _opts = toJSON . unK1--instance GToJSON U1 where-    -- Empty constructors are encoded to an empty array:-    gToJSON _opts _ = emptyArray--instance (ConsToJSON a) => GToJSON (C1 c a) where-    -- Constructors need to be encoded differently depending on whether they're-    -- a record or not. This distinction is made by 'consToJSON':-    gToJSON opts = consToJSON opts . unM1--instance ( WriteProduct a, WriteProduct b-         , ProductSize  a, ProductSize  b ) => GToJSON (a :*: b) where-    -- Products are encoded to an array. Here we allocate a mutable vector of-    -- the same size as the product and write the product's elements to it using-    -- 'writeProduct':-    gToJSON opts p =-        Array $ V.create $ do-          mv <- VM.unsafeNew lenProduct-          writeProduct opts mv 0 lenProduct p-          return mv-        where-          lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)-                       productSize--instance ( AllNullary (a :+: b) allNullary-         , SumToJSON  (a :+: b) allNullary ) => GToJSON (a :+: b) where-    -- If all constructors of a sum datatype are nullary and the-    -- 'allNullaryToStringTag' option is set they are encoded to-    -- strings.  This distinction is made by 'sumToJSON':-    gToJSON opts = (unTagged :: Tagged allNullary Value -> Value)-                 . sumToJSON opts------------------------------------------------------------------------------------- Generic toEncoding--instance OVERLAPPABLE_ (GToEncoding a) => GToEncoding (M1 i c a) where-    -- Meta-information, which is not handled elsewhere, is ignored:-    gToEncoding opts = gToEncoding opts . unM1--instance (ToJSON a) => GToEncoding (K1 i a) where-    -- Constant values are encoded using their ToJSON instance:-    gToEncoding _opts = toEncoding . unK1--instance GToEncoding U1 where-    -- Empty constructors are encoded to an empty array:-    gToEncoding _opts _ = emptyArray_--instance (ConsToEncoding a) => GToEncoding (C1 c a) where-    -- Constructors need to be encoded differently depending on whether they're-    -- a record or not. This distinction is made by 'consToEncoding':-    gToEncoding opts = Encoding . consToEncoding opts . unM1--instance ( EncodeProduct a, EncodeProduct b ) => GToEncoding (a :*: b) where-    -- Products are encoded to an array. Here we allocate a mutable vector of-    -- the same size as the product and write the product's elements to it using-    -- 'encodeProduct':-    gToEncoding opts p = Encoding $-                         B.char7 '[' <> encodeProduct opts p <> B.char7 ']'--instance ( AllNullary    (a :+: b) allNullary-         , SumToEncoding (a :+: b) allNullary ) => GToEncoding (a :+: b) where-    -- If all constructors of a sum datatype are nullary and the-    -- 'allNullaryToStringTag' option is set they are encoded to-    -- strings.  This distinction is made by 'sumToEncoding':-    gToEncoding opts = Encoding .-                       (unTagged :: Tagged allNullary B.Builder -> B.Builder) .-                       sumToEncoding opts------------------------------------------------------------------------------------class SumToJSON f allNullary where-    sumToJSON :: Options -> f a -> Tagged allNullary Value--instance ( GetConName               f-         , TaggedObjectPairs        f-         , ObjectWithSingleFieldObj f-         , TwoElemArrayObj          f ) => SumToJSON f True where-    sumToJSON opts-        | allNullaryToStringTag opts = Tagged . String . pack-                                     . constructorTagModifier opts . getConName-        | otherwise = Tagged . nonAllNullarySumToJSON opts--instance ( TwoElemArrayObj          f-         , TaggedObjectPairs        f-         , ObjectWithSingleFieldObj f ) => SumToJSON f False where-    sumToJSON opts = Tagged . nonAllNullarySumToJSON opts--nonAllNullarySumToJSON :: ( TwoElemArrayObj          f-                          , TaggedObjectPairs        f-                          , ObjectWithSingleFieldObj f-                          ) => Options -> f a -> Value-nonAllNullarySumToJSON opts =-    case sumEncoding opts of-      TaggedObject{..}      ->-        object . taggedObjectPairs opts tagFieldName contentsFieldName-      ObjectWithSingleField -> Object . objectWithSingleFieldObj opts-      TwoElemArray          -> Array  . twoElemArrayObj opts------------------------------------------------------------------------------------class SumToEncoding f allNullary where-    sumToEncoding :: Options -> f a -> Tagged allNullary B.Builder--instance ( GetConName               f-         , TaggedObjectEnc          f-         , ObjectWithSingleFieldEnc f-         , TwoElemArrayEnc          f ) => SumToEncoding f True where-    sumToEncoding opts-        | allNullaryToStringTag opts = Tagged . builder .-                                       constructorTagModifier opts . getConName-        | otherwise = Tagged . nonAllNullarySumToEncoding opts--instance ( TwoElemArrayEnc          f-         , TaggedObjectEnc          f-         , ObjectWithSingleFieldEnc f ) => SumToEncoding f False where-    sumToEncoding opts = Tagged . nonAllNullarySumToEncoding opts--nonAllNullarySumToEncoding :: ( TwoElemArrayEnc          f-                              , TaggedObjectEnc          f-                              , ObjectWithSingleFieldEnc f-                              ) => Options -> f a -> B.Builder-nonAllNullarySumToEncoding opts =-    case sumEncoding opts of-      TaggedObject{..}      ->-        taggedObjectEnc opts tagFieldName contentsFieldName-      ObjectWithSingleField -> objectWithSingleFieldEnc opts-      TwoElemArray          -> twoElemArrayEnc opts------------------------------------------------------------------------------------class TaggedObjectPairs f where-    taggedObjectPairs :: Options -> String -> String -> f a -> [Pair]--instance ( TaggedObjectPairs a-         , TaggedObjectPairs b ) => TaggedObjectPairs (a :+: b) where-    taggedObjectPairs opts tagFieldName contentsFieldName (L1 x) =-        taggedObjectPairs opts tagFieldName contentsFieldName     x-    taggedObjectPairs opts tagFieldName contentsFieldName (R1 x) =-        taggedObjectPairs opts tagFieldName contentsFieldName     x--instance ( IsRecord           a isRecord-         , TaggedObjectPairs' a isRecord-         , Constructor c ) => TaggedObjectPairs (C1 c a) where-    taggedObjectPairs opts tagFieldName contentsFieldName =-        (pack tagFieldName .= constructorTagModifier opts-                                 (conName (undefined :: t c a p)) :) .-        (unTagged :: Tagged isRecord [Pair] -> [Pair]) .-          taggedObjectPairs' opts contentsFieldName . unM1--class TaggedObjectPairs' f isRecord where-    taggedObjectPairs' :: Options -> String -> f a -> Tagged isRecord [Pair]--instance (RecordToPairs f) => TaggedObjectPairs' f True where-    taggedObjectPairs' opts _ = Tagged . toList . recordToPairs opts--instance (GToJSON f) => TaggedObjectPairs' f False where-    taggedObjectPairs' opts contentsFieldName =-        Tagged . (:[]) . (pack contentsFieldName .=) . gToJSON opts------------------------------------------------------------------------------------class TaggedObjectEnc f where-    taggedObjectEnc :: Options -> String -> String -> f a -> B.Builder--instance ( TaggedObjectEnc a-         , TaggedObjectEnc b ) => TaggedObjectEnc (a :+: b) where-    taggedObjectEnc opts tagFieldName contentsFieldName (L1 x) =-        taggedObjectEnc opts tagFieldName contentsFieldName     x-    taggedObjectEnc opts tagFieldName contentsFieldName (R1 x) =-        taggedObjectEnc opts tagFieldName contentsFieldName     x--instance ( IsRecord         a isRecord-         , TaggedObjectEnc' a isRecord-         , Constructor c ) => TaggedObjectEnc (C1 c a) where-    taggedObjectEnc opts tagFieldName contentsFieldName v =-        B.char7 '{' <>-        (builder tagFieldName <>-         B.char7 ':' <>-         builder (constructorTagModifier opts (conName (undefined :: t c a p)))) <>-        B.char7 ',' <>-        ((unTagged :: Tagged isRecord B.Builder -> B.Builder) .-         taggedObjectEnc' opts contentsFieldName . unM1 $ v) <>-        B.char7 '}'--class TaggedObjectEnc' f isRecord where-    taggedObjectEnc' :: Options -> String -> f a -> Tagged isRecord B.Builder--instance (RecordToEncoding f) => TaggedObjectEnc' f True where-    taggedObjectEnc' opts _ = Tagged . recordToEncoding opts--instance (GToEncoding f) => TaggedObjectEnc' f False where-    taggedObjectEnc' opts contentsFieldName =-        Tagged . (\z -> builder contentsFieldName <> B.char7 ':' <> z) .-        gbuilder opts-------------------------------------------------------------------------------------- | Get the name of the constructor of a sum datatype.-class GetConName f where-    getConName :: f a -> String--instance (GetConName a, GetConName b) => GetConName (a :+: b) where-    getConName (L1 x) = getConName x-    getConName (R1 x) = getConName x--instance (Constructor c) => GetConName (C1 c a) where-    getConName = conName------------------------------------------------------------------------------------class TwoElemArrayObj f where-    twoElemArrayObj :: Options -> f a -> V.Vector Value--instance (TwoElemArrayObj a, TwoElemArrayObj b) => TwoElemArrayObj (a :+: b) where-    twoElemArrayObj opts (L1 x) = twoElemArrayObj opts x-    twoElemArrayObj opts (R1 x) = twoElemArrayObj opts x--instance ( GToJSON a, ConsToJSON a-         , Constructor c ) => TwoElemArrayObj (C1 c a) where-    twoElemArrayObj opts x = V.create $ do-      mv <- VM.unsafeNew 2-      VM.unsafeWrite mv 0 $ String $ pack $ constructorTagModifier opts-                                   $ conName (undefined :: t c a p)-      VM.unsafeWrite mv 1 $ gToJSON opts x-      return mv------------------------------------------------------------------------------------class TwoElemArrayEnc f where-    twoElemArrayEnc :: Options -> f a -> B.Builder--instance (TwoElemArrayEnc a, TwoElemArrayEnc b) => TwoElemArrayEnc (a :+: b) where-    twoElemArrayEnc opts (L1 x) = twoElemArrayEnc opts x-    twoElemArrayEnc opts (R1 x) = twoElemArrayEnc opts x--instance ( GToEncoding a, ConsToEncoding a-         , Constructor c ) => TwoElemArrayEnc (C1 c a) where-    twoElemArrayEnc opts x = fromEncoding . tuple $-      builder (constructorTagModifier opts (conName (undefined :: t c a p))) >*<-      gbuilder opts x------------------------------------------------------------------------------------class ConsToJSON f where-    consToJSON     :: Options -> f a -> Value--class ConsToJSON' f isRecord where-    consToJSON'     :: Options -> Bool -- ^ Are we a record with one field?-                    -> f a -> Tagged isRecord Value--instance ( IsRecord    f isRecord-         , ConsToJSON' f isRecord ) => ConsToJSON f where-    consToJSON opts = (unTagged :: Tagged isRecord Value -> Value)-                    . consToJSON' opts (isUnary (undefined :: f a))--instance (RecordToPairs f) => ConsToJSON' f True where-    consToJSON' opts isUn f = let-      vals = toList $ recordToPairs opts f-      in case (unwrapUnaryRecords opts,isUn,vals) of-        (True,True,[(_,val)]) -> Tagged val-        _ -> Tagged $ object vals--instance GToJSON f => ConsToJSON' f False where-    consToJSON' opts _ = Tagged . gToJSON opts------------------------------------------------------------------------------------class ConsToEncoding f where-    consToEncoding :: Options -> f a -> B.Builder--class ConsToEncoding' f isRecord where-    consToEncoding' :: Options -> Bool -- ^ Are we a record with one field?-                    -> f a -> Tagged isRecord B.Builder--instance ( IsRecord        f isRecord-         , ConsToEncoding' f isRecord ) => ConsToEncoding f where-    consToEncoding opts = (unTagged :: Tagged isRecord B.Builder -> B.Builder)-                          . consToEncoding' opts (isUnary (undefined :: f a))--instance (RecordToEncoding f) => ConsToEncoding' f True where-    consToEncoding' opts isUn x-      | (True,True) <- (unwrapUnaryRecords opts,isUn) = Tagged $   recordToEncoding opts x-      | otherwise = Tagged $-          B.char7 '{' <>-          recordToEncoding opts x <>-          B.char7 '}'--instance GToEncoding f => ConsToEncoding' f False where-    consToEncoding' opts _ = Tagged . gbuilder opts------------------------------------------------------------------------------------class RecordToPairs f where-    recordToPairs    :: Options -> f a -> DList Pair--instance (RecordToPairs a, RecordToPairs b) => RecordToPairs (a :*: b) where-    recordToPairs opts (a :*: b) = recordToPairs opts a <>-                                   recordToPairs opts b--instance (Selector s, GToJSON a) => RecordToPairs (S1 s a) where-    recordToPairs = fieldToPair--instance OVERLAPPING_ (Selector s, ToJSON a) =>-  RecordToPairs (S1 s (K1 i (Maybe a))) where-    recordToPairs opts (M1 k1) | omitNothingFields opts-                               , K1 Nothing <- k1 = empty-    recordToPairs opts m1 = fieldToPair opts m1--fieldToPair :: (Selector s, GToJSON a) => Options -> S1 s a p -> DList Pair-fieldToPair opts m1 = pure ( pack $ fieldLabelModifier opts $ selName m1-                           , gToJSON opts (unM1 m1)-                           )------------------------------------------------------------------------------------class RecordToEncoding f where-    recordToEncoding :: Options -> f a -> B.Builder--instance (RecordToEncoding a, RecordToEncoding b) => RecordToEncoding (a :*: b) where-    recordToEncoding opts (a :*: b) = recordToEncoding opts a <>-                                      B.char7 ',' <>-                                      recordToEncoding opts b--instance (Selector s, GToEncoding a) => RecordToEncoding (S1 s a) where-    recordToEncoding = fieldToEncoding--instance OVERLAPPING_ (Selector s, ToJSON a) =>-  RecordToEncoding (S1 s (K1 i (Maybe a))) where-    recordToEncoding opts (M1 k1) | omitNothingFields opts-                                  , K1 Nothing <- k1 = mempty-    recordToEncoding opts m1 = fieldToEncoding opts m1--fieldToEncoding :: (Selector s, GToEncoding a) => Options -> S1 s a p -> B.Builder-fieldToEncoding opts m1 =-    builder (fieldLabelModifier opts $ selName m1) <>-    B.char7 ':' <>-    gbuilder opts (unM1 m1)------------------------------------------------------------------------------------class WriteProduct f where-    writeProduct :: Options-                 -> VM.MVector s Value-                 -> Int -- ^ index-                 -> Int -- ^ length-                 -> f a-                 -> ST s ()--instance ( WriteProduct a-         , WriteProduct b ) => WriteProduct (a :*: b) where-    writeProduct opts mv ix len (a :*: b) = do-      writeProduct opts mv ix  lenL a-      writeProduct opts mv ixR lenR b-        where-          lenL = len `unsafeShiftR` 1-          lenR = len - lenL-          ixR  = ix  + lenL--instance OVERLAPPABLE_ (GToJSON a) => WriteProduct a where-    writeProduct opts mv ix _ = VM.unsafeWrite mv ix . gToJSON opts------------------------------------------------------------------------------------class EncodeProduct f where-    encodeProduct :: Options -> f a -> B.Builder--instance ( EncodeProduct a-         , EncodeProduct b ) => EncodeProduct (a :*: b) where-    encodeProduct opts (a :*: b) = encodeProduct opts a <>-                                   B.char7 ',' <>-                                   encodeProduct opts b--instance OVERLAPPABLE_ (GToEncoding a) => EncodeProduct a where-    encodeProduct opts = gbuilder opts------------------------------------------------------------------------------------class ObjectWithSingleFieldObj f where-    objectWithSingleFieldObj :: Options -> f a -> Object--instance ( ObjectWithSingleFieldObj a-         , ObjectWithSingleFieldObj b ) => ObjectWithSingleFieldObj (a :+: b) where-    objectWithSingleFieldObj opts (L1 x) = objectWithSingleFieldObj opts x-    objectWithSingleFieldObj opts (R1 x) = objectWithSingleFieldObj opts x--instance ( GToJSON a, ConsToJSON a-         , Constructor c ) => ObjectWithSingleFieldObj (C1 c a) where-    objectWithSingleFieldObj opts = H.singleton typ . gToJSON opts-        where-          typ = pack $ constructorTagModifier opts $-                         conName (undefined :: t c a p)------------------------------------------------------------------------------------class ObjectWithSingleFieldEnc f where-    objectWithSingleFieldEnc :: Options -> f a -> B.Builder--instance ( ObjectWithSingleFieldEnc a-         , ObjectWithSingleFieldEnc b ) => ObjectWithSingleFieldEnc (a :+: b) where-    objectWithSingleFieldEnc opts (L1 x) = objectWithSingleFieldEnc opts x-    objectWithSingleFieldEnc opts (R1 x) = objectWithSingleFieldEnc opts x--instance ( GToEncoding a, ConsToEncoding a-         , Constructor c ) => ObjectWithSingleFieldEnc (C1 c a) where-    objectWithSingleFieldEnc opts v =-      B.char7 '{' <>-      builder (constructorTagModifier opts-               (conName (undefined :: t c a p))) <>-      B.char7 ':' <>-      gbuilder opts v <>-      B.char7 '}'--gbuilder :: GToEncoding f => Options -> f a -> Builder-gbuilder opts = fromEncoding . gToEncoding opts------------------------------------------------------------------------------------- Generic parseJSON--instance OVERLAPPABLE_ (GFromJSON a) => GFromJSON (M1 i c a) where-    -- Meta-information, which is not handled elsewhere, is just added to the-    -- parsed value:-    gParseJSON opts = fmap M1 . gParseJSON opts--instance (FromJSON a) => GFromJSON (K1 i a) where-    -- Constant values are decoded using their FromJSON instance:-    gParseJSON _opts = fmap K1 . parseJSON--instance GFromJSON U1 where-    -- Empty constructors are expected to be encoded as an empty array:-    gParseJSON _opts v-        | isEmptyArray v = pure U1-        | otherwise      = typeMismatch "unit constructor (U1)" v--instance (ConsFromJSON a) => GFromJSON (C1 c a) where-    -- Constructors need to be decoded differently depending on whether they're-    -- a record or not. This distinction is made by consParseJSON:-    gParseJSON opts = fmap M1 . consParseJSON opts--instance ( FromProduct a, FromProduct b-         , ProductSize a, ProductSize b ) => GFromJSON (a :*: b) where-    -- Products are expected to be encoded to an array. Here we check whether we-    -- got an array of the same size as the product, then parse each of the-    -- product's elements using parseProduct:-    gParseJSON opts = withArray "product (:*:)" $ \arr ->-      let lenArray = V.length arr-          lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)-                       productSize in-      if lenArray == lenProduct-      then parseProduct opts arr 0 lenProduct-      else fail $ "When expecting a product of " ++ show lenProduct ++-                  " values, encountered an Array of " ++ show lenArray ++-                  " elements instead"--instance ( AllNullary (a :+: b) allNullary-         , ParseSum   (a :+: b) allNullary ) => GFromJSON   (a :+: b) where-    -- If all constructors of a sum datatype are nullary and the-    -- 'allNullaryToStringTag' option is set they are expected to be-    -- encoded as strings.  This distinction is made by 'parseSum':-    gParseJSON opts = (unTagged :: Tagged allNullary (Parser ((a :+: b) d)) ->-                                                     (Parser ((a :+: b) d)))-                    . parseSum opts------------------------------------------------------------------------------------class ParseSum f allNullary where-    parseSum :: Options -> Value -> Tagged allNullary (Parser (f a))--instance ( SumFromString    (a :+: b)-         , FromPair         (a :+: b)-         , FromTaggedObject (a :+: b) ) => ParseSum (a :+: b) True where-    parseSum opts-        | allNullaryToStringTag opts = Tagged . parseAllNullarySum    opts-        | otherwise                  = Tagged . parseNonAllNullarySum opts--instance ( FromPair         (a :+: b)-         , FromTaggedObject (a :+: b) ) => ParseSum (a :+: b) False where-    parseSum opts = Tagged . parseNonAllNullarySum opts------------------------------------------------------------------------------------parseAllNullarySum :: SumFromString f => Options -> Value -> Parser (f a)-parseAllNullarySum opts = withText "Text" $ \key ->-                            maybe (notFound $ unpack key) return $-                              parseSumFromString opts key--class SumFromString f where-    parseSumFromString :: Options -> Text -> Maybe (f a)--instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where-    parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>-                                  (R1 <$> parseSumFromString opts key)--instance (Constructor c) => SumFromString (C1 c U1) where-    parseSumFromString opts key | key == name = Just $ M1 U1-                                | otherwise   = Nothing-        where-          name = pack $ constructorTagModifier opts $-                          conName (undefined :: t c U1 p)------------------------------------------------------------------------------------parseNonAllNullarySum :: ( FromPair                       (a :+: b)-                         , FromTaggedObject               (a :+: b)-                         ) => Options -> Value -> Parser ((a :+: b) c)-parseNonAllNullarySum opts =-    case sumEncoding opts of-      TaggedObject{..} ->-          withObject "Object" $ \obj -> do-            tag <- obj .: pack tagFieldName-            fromMaybe (notFound $ unpack tag) $-              parseFromTaggedObject opts contentsFieldName obj tag--      ObjectWithSingleField ->-          withObject "Object" $ \obj ->-            case H.toList obj of-              [pair@(tag, _)] -> fromMaybe (notFound $ unpack tag) $-                                   parsePair opts pair-              _ -> fail "Object doesn't have a single field"--      TwoElemArray ->-          withArray "Array" $ \arr ->-            if V.length arr == 2-            then case V.unsafeIndex arr 0 of-                   String tag -> fromMaybe (notFound $ unpack tag) $-                                   parsePair opts (tag, V.unsafeIndex arr 1)-                   _ -> fail "First element is not a String"-            else fail "Array doesn't have 2 elements"------------------------------------------------------------------------------------class FromTaggedObject f where-    parseFromTaggedObject :: Options -> String -> Object -> Text-                          -> Maybe (Parser (f a))--instance (FromTaggedObject a, FromTaggedObject b) =>-    FromTaggedObject (a :+: b) where-        parseFromTaggedObject opts contentsFieldName obj tag =-            (fmap L1 <$> parseFromTaggedObject opts contentsFieldName obj tag) <|>-            (fmap R1 <$> parseFromTaggedObject opts contentsFieldName obj tag)--instance ( FromTaggedObject' f-         , Constructor c ) => FromTaggedObject (C1 c f) where-    parseFromTaggedObject opts contentsFieldName obj tag-        | tag == name = Just $ M1 <$> parseFromTaggedObject'-                                        opts contentsFieldName obj-        | otherwise = Nothing-        where-          name = pack $ constructorTagModifier opts $-                          conName (undefined :: t c f p)------------------------------------------------------------------------------------class FromTaggedObject' f where-    parseFromTaggedObject' :: Options -> String -> Object -> Parser (f a)--class FromTaggedObject'' f isRecord where-    parseFromTaggedObject'' :: Options -> String -> Object-                            -> Tagged isRecord (Parser (f a))--instance ( IsRecord             f isRecord-         , FromTaggedObject''   f isRecord-         ) => FromTaggedObject' f where-    parseFromTaggedObject' opts contentsFieldName =-        (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a)) .-        parseFromTaggedObject'' opts contentsFieldName--instance (FromRecord f) => FromTaggedObject'' f True where-    parseFromTaggedObject'' opts _ = Tagged . parseRecord opts Nothing--instance (GFromJSON f) => FromTaggedObject'' f False where-    parseFromTaggedObject'' opts contentsFieldName = Tagged .-      (gParseJSON opts <=< (.: pack contentsFieldName))------------------------------------------------------------------------------------class ConsFromJSON f where-    consParseJSON  :: Options -> Value -> Parser (f a)--class ConsFromJSON' f isRecord where-    consParseJSON' :: Options -> (Maybe Text) -- ^ A dummy label-                                           --   (Nothing to use proper label)-                   -> Value -> Tagged isRecord (Parser (f a))--instance ( IsRecord        f isRecord-         , ConsFromJSON'   f isRecord-         ) => ConsFromJSON f where-    consParseJSON opts v = let-      (v2,lab) = case (unwrapUnaryRecords opts,isUnary (undefined :: f a)) of-                       -- use a dummy object with a dummy label-        (True,True) -> ((object [(pack "dummy",v)]),Just $ pack "dummy")-        _ ->(v,Nothing)-      in (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a))-                       $ consParseJSON' opts lab v2---instance (FromRecord f) => ConsFromJSON' f True where-    consParseJSON' opts mlab = Tagged . (withObject "record (:*:)"-                                $ parseRecord opts mlab)--instance (GFromJSON f) => ConsFromJSON' f False where-    consParseJSON' opts _ = Tagged . gParseJSON opts------------------------------------------------------------------------------------class FromRecord f where-    parseRecord :: Options -> (Maybe Text) -- ^ A dummy label-                                           --   (Nothing to use proper label)-                 -> Object -> Parser (f a)--instance (FromRecord a, FromRecord b) => FromRecord (a :*: b) where-    parseRecord opts _ obj = (:*:) <$> parseRecord opts Nothing obj-                                   <*> parseRecord opts Nothing obj--instance (Selector s, GFromJSON a) => FromRecord (S1 s a) where-    parseRecord opts (Just lab) = maybe (notFound $ unpack lab)-                      (gParseJSON opts) . H.lookup lab-    parseRecord opts Nothing    = maybe (notFound label)-                      (gParseJSON opts) . H.lookup (pack label)-        where-          label = fieldLabelModifier opts $ selName (undefined :: t s a p)--instance OVERLAPPING_ (Selector s, FromJSON a) =>-  FromRecord (S1 s (K1 i (Maybe a))) where-    parseRecord _ (Just lab) obj = (M1 . K1) <$> obj .:? lab-    parseRecord opts Nothing obj = (M1 . K1) <$> obj .:? pack label-        where-          label = fieldLabelModifier opts $-                    selName (undefined :: t s (K1 i (Maybe a)) p)------------------------------------------------------------------------------------class ProductSize f where-    productSize :: Tagged2 f Int--instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where-    productSize = Tagged2 $ unTagged2 (productSize :: Tagged2 a Int) +-                            unTagged2 (productSize :: Tagged2 b Int)--instance ProductSize (S1 s a) where-    productSize = Tagged2 1------------------------------------------------------------------------------------class FromProduct f where-    parseProduct :: Options -> Array -> Int -> Int -> Parser (f a)--instance (FromProduct a, FromProduct b) => FromProduct (a :*: b) where-    parseProduct opts arr ix len =-        (:*:) <$> parseProduct opts arr ix  lenL-              <*> parseProduct opts arr ixR lenR-        where-          lenL = len `unsafeShiftR` 1-          ixR  = ix + lenL-          lenR = len - lenL--instance (GFromJSON a) => FromProduct (S1 s a) where-    parseProduct opts arr ix _ = gParseJSON opts $ V.unsafeIndex arr ix----------------------------------------------------------------------------------+-- Helpers for generic derivations. -class FromPair f where-    parsePair :: Options -> Pair -> Maybe (Parser (f a))+module Data.Aeson.Types.Generic+    (+      IsRecord(..)+    , AllNullary+    , Tagged2(..)+    , True+    , False+    , And+    , Zero+    , One+    , ProductSize(..)+    ) where -instance (FromPair a, FromPair b) => FromPair (a :+: b) where-    parsePair opts pair = (fmap L1 <$> parsePair opts pair) <|>-                          (fmap R1 <$> parsePair opts pair)+import Prelude ()+import Prelude.Compat -instance (Constructor c, GFromJSON a, ConsFromJSON a) => FromPair (C1 c a) where-    parsePair opts (tag, value)-        | tag == tag' = Just $ gParseJSON opts value-        | otherwise   = Nothing-        where-          tag' = pack $ constructorTagModifier opts $-                          conName (undefined :: t c a p)+import GHC.Generics  -------------------------------------------------------------------------------- @@ -745,6 +57,9 @@ #endif instance (IsRecord f isRecord) => IsRecord (M1 S c f) isRecord instance IsRecord (K1 i c) True+instance IsRecord Par1 True+instance IsRecord (Rec1 f) True+instance IsRecord (f :.: g) True instance IsRecord U1 False   where isUnary = const False @@ -758,9 +73,14 @@          ) => AllNullary (a :+: b) allNullary instance AllNullary a allNullary => AllNullary (M1 i c a) allNullary instance AllNullary (a :*: b) False+instance AllNullary (a :.: b) False instance AllNullary (K1 i c) False+instance AllNullary Par1 False+instance AllNullary (Rec1 f) False instance AllNullary U1 True +newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}+ --------------------------------------------------------------------------------  data True@@ -775,12 +95,20 @@  -------------------------------------------------------------------------------- -newtype Tagged s b = Tagged {unTagged :: b}+-- | A type-level indicator that 'ToJSON' or 'FromJSON' is being derived generically.+data Zero -newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}+-- | A type-level indicator that 'ToJSON1' or 'FromJSON1' is being derived generically.+data One  -------------------------------------------------------------------------------- -notFound :: String -> Parser a-notFound key = fail $ "The key \"" ++ key ++ "\" was not found"-{-# INLINE notFound #-}+class ProductSize f where+    productSize :: Tagged2 f Int++instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where+    productSize = Tagged2 $ unTagged2 (productSize :: Tagged2 a Int) ++                            unTagged2 (productSize :: Tagged2 b Int)++instance ProductSize (S1 s a) where+    productSize = Tagged2 1
− Data/Aeson/Types/Instances.hs
@@ -1,1738 +0,0 @@-{-# LANGUAGE CPP, BangPatterns, DeriveDataTypeable, FlexibleContexts,-    FlexibleInstances, GeneralizedNewtypeDeriving,-    OverloadedStrings, UndecidableInstances,-    ViewPatterns #-}-{-# LANGUAGE DefaultSignatures #-}---- Needed for Tagged, Const and Proxy instances-#if __GLASGOW_HASKELL__ >= 706-{-# LANGUAGE PolyKinds #-}-#endif--#define NEEDS_INCOHERENT-#include "overlapping-compat.h"--{-# OPTIONS_GHC -fno-warn-orphans #-}---- TODO: Drop this when we remove support for Data.Attoparsec.Number-{-# OPTIONS_GHC -fno-warn-deprecations #-}---- |--- Module:      Data.Aeson.Types.Instances--- Copyright:   (c) 2011-2016 Bryan O'Sullivan---              (c) 2011 MailRank, Inc.--- License:     BSD3--- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>--- Stability:   experimental--- Portability: portable------ Types for working with JSON data.--module Data.Aeson.Types.Instances-    (-    -- * Type classes-    -- ** Core JSON classes-      FromJSON(..)-    , ToJSON(..)-    , KeyValue(..)-    -- ** Generic JSON classes-    , GFromJSON(..)-    , GToJSON(..)-    , GToEncoding(..)-    , genericToJSON-    , genericToEncoding-    , genericParseJSON--    -- * Types-    , DotNetTime(..)--      -- * Inspecting @'Value's@-    , withObject-    , withText-    , withArray-    , withNumber-    , withScientific-    , withBool--    -- * Functions-    , fromJSON-    , ifromJSON-    , (.:)-    , (.:?)-    , (.:!)-    , (.!=)-    , tuple-    , (>*<)-    , typeMismatch-    ) where--import Control.Applicative (Const(..))-import Data.Aeson.Encode.Functions (brackets, builder, encode, foldable, list)-import Data.Aeson.Functions (hashMapKey, mapHashKeyVal, mapKey, mapKeyVal)-import Data.Aeson.Types.Class-import Data.Aeson.Types.Internal-import Data.Attoparsec.Number (Number(..))-import Data.Fixed (Fixed, HasResolution)-import Data.Foldable (toList)-import Data.Functor.Identity (Identity(..))-import Data.Hashable (Hashable(..))-import Data.Int (Int8, Int16, Int32, Int64)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe (fromMaybe)-import Data.Monoid ((<>))-import Data.Monoid (Dual(..), First(..), Last(..))-import Data.Proxy (Proxy(..))-import Data.Ratio (Ratio, (%), numerator, denominator)-import Data.Scientific (Scientific)-import Data.Tagged (Tagged(..))-import Data.Text (Text, pack, unpack)-import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay, UTCTime,-                  ZonedTime)-import Data.Time.Format (FormatTime, formatTime, parseTime)-import Data.Traversable as Tr (sequence)-import Data.Vector (Vector)-import Data.Word (Word8, Word16, Word32, Word64)-import Data.Version (Version, showVersion, parseVersion)-import Text.ParserCombinators.ReadP (readP_to_S)-import Foreign.Storable (Storable)-import Numeric.Natural (Natural)-import Prelude hiding (foldr)-import qualified Data.Aeson.Encode.Builder as E-import qualified Data.Aeson.Parser.Time as Time-import qualified Data.ByteString.Builder as B-import qualified Data.ByteString.Lazy as L-import qualified Data.HashMap.Strict as H-import qualified Data.HashSet as HashSet-import qualified Data.IntMap as IntMap-import qualified Data.IntSet as IntSet-import qualified Data.Map as M-import qualified Data.Scientific as Scientific-import qualified Data.Sequence as Seq-import qualified Data.Set as Set-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Text.Lazy as LT-import qualified Data.Tree as Tree-import qualified Data.Vector as V-import qualified Data.Vector.Generic as VG-import qualified Data.Vector.Mutable as VM (unsafeNew, unsafeWrite)-import qualified Data.Vector.Primitive as VP-import qualified Data.Vector.Storable as VS-import qualified Data.Vector.Unboxed as VU--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative ((<$>), (<*>), pure)-import Data.Monoid (mempty)-import Data.Word (Word)-#endif--#if MIN_VERSION_time(1,5,0)-import Data.Time.Format (defaultTimeLocale)-#else-import System.Locale (defaultTimeLocale)-#endif--parseIndexedJSON :: FromJSON a => Int -> Value -> Parser a-parseIndexedJSON idx value = parseJSON value <?> Index idx--instance (ToJSON a) => ToJSON (Identity a) where-    toJSON (Identity a) = toJSON a-    {-# INLINE toJSON #-}--    toEncoding (Identity a) = toEncoding a-    {-# INLINE toEncoding #-}--instance (FromJSON a) => FromJSON (Identity a) where-    parseJSON a      = Identity <$> parseJSON a-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (Maybe a) where-    toJSON (Just a) = toJSON a-    toJSON Nothing  = Null-    {-# INLINE toJSON #-}--    toEncoding (Just a) = toEncoding a-    toEncoding Nothing  = Encoding E.null_-    {-# INLINE toEncoding #-}--instance (FromJSON a) => FromJSON (Maybe a) where-    parseJSON Null   = pure Nothing-    parseJSON a      = Just <$> parseJSON a-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where-    toJSON (Left a)  = object [left  .= a]-    toJSON (Right b) = object [right .= b]-    {-# INLINE toJSON #-}--    toEncoding (Left a) = Encoding $-      B.shortByteString "{\"Left\":" <> builder a <> B.char7 '}'-    toEncoding (Right a) = Encoding $-      B.shortByteString "{\"Right\":" <> builder a <> B.char7 '}'-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where-    parseJSON (Object (H.toList -> [(key, value)]))-        | key == left  = Left  <$> parseJSON value <?> Key left-        | key == right = Right <$> parseJSON value <?> Key right-    parseJSON _        = fail $-        "expected an object with a single property " ++-        "where the property key should be either " ++-        "\"Left\" or \"Right\""-    {-# INLINE parseJSON #-}--left, right :: Text-left  = "Left"-right = "Right"--instance ToJSON Bool where-    toJSON = Bool-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.bool-    {-# INLINE toEncoding #-}--instance FromJSON Bool where-    parseJSON = withBool "Bool" pure-    {-# INLINE parseJSON #-}--instance ToJSON Ordering where-  toJSON     = toJSON     . orderingToText-  toEncoding = toEncoding . orderingToText--orderingToText :: Ordering -> T.Text-orderingToText o = case o of-                     LT -> "LT"-                     EQ -> "EQ"-                     GT -> "GT"--instance FromJSON Ordering where-  parseJSON = withText "Ordering" $ \s ->-    case s of-      "LT" -> return LT-      "EQ" -> return EQ-      "GT" -> return GT-      _ -> fail "Parsing Ordering value failed: expected \"LT\", \"EQ\", or \"GT\""--instance ToJSON () where-    toJSON _ = emptyArray-    {-# INLINE toJSON #-}--    toEncoding _ = E.emptyArray_-    {-# INLINE toEncoding #-}--instance FromJSON () where-    parseJSON = withArray "()" $ \v ->-                  if V.null v-                    then pure ()-                    else fail "Expected an empty array"-    {-# INLINE parseJSON #-}--instance INCOHERENT_ ToJSON [Char] where-    toJSON = String . T.pack-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.string-    {-# INLINE toEncoding #-}--instance INCOHERENT_ FromJSON [Char] where-    parseJSON = withText "String" $ pure . T.unpack-    {-# INLINE parseJSON #-}--instance ToJSON Char where-    toJSON = String . T.singleton-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.string . (:[])-    {-# INLINE toEncoding #-}--instance FromJSON Char where-    parseJSON = withText "Char" $ \t ->-                  if T.compareLength t 1 == EQ-                    then pure $ T.head t-                    else fail "Expected a string of length 1"-    {-# INLINE parseJSON #-}--instance ToJSON Scientific where-    toJSON = Number-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.number-    {-# INLINE toEncoding #-}--instance FromJSON Scientific where-    parseJSON = withScientific "Scientific" pure-    {-# INLINE parseJSON #-}--instance ToJSON Double where-    toJSON = realFloatToJSON-    {-# INLINE toJSON #-}--    toEncoding = realFloatToEncoding-    {-# INLINE toEncoding #-}--instance FromJSON Double where-    parseJSON = parseRealFloat "Double"-    {-# INLINE parseJSON #-}--instance ToJSON Number where-    toJSON (D d) = toJSON d-    toJSON (I i) = toJSON i-    {-# INLINE toJSON #-}--    toEncoding (D d) = toEncoding d-    toEncoding (I i) = toEncoding i-    {-# INLINE toEncoding #-}--instance FromJSON Number where-    parseJSON (Number s) = pure $ scientificToNumber s-    parseJSON Null       = pure (D (0/0))-    parseJSON v          = typeMismatch "Number" v-    {-# INLINE parseJSON #-}--instance ToJSON Float where-    toJSON = realFloatToJSON-    {-# INLINE toJSON #-}--    toEncoding = realFloatToEncoding-    {-# INLINE toEncoding #-}--instance FromJSON Float where-    parseJSON = parseRealFloat "Float"-    {-# INLINE parseJSON #-}--instance ToJSON (Ratio Integer) where-    toJSON r = object [ "numerator"   .= numerator   r-                      , "denominator" .= denominator r-                      ]-    {-# INLINE toJSON #-}--    toEncoding r = Encoding $-      B.shortByteString "{\"numerator\":" <> builder (numerator r) <>-      B.shortByteString ",\"denominator\":" <> builder (denominator r) <>-      B.char7 '}'-    {-# INLINE toEncoding #-}--instance FromJSON (Ratio Integer) where-    parseJSON = withObject "Rational" $ \obj ->-                  (%) <$> obj .: "numerator"-                      <*> obj .: "denominator"-    {-# INLINE parseJSON #-}--instance HasResolution a => ToJSON (Fixed a) where-    toJSON = Number . realToFrac-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.number . realToFrac-    {-# INLINE toEncoding #-}---- | /WARNING:/ Only parse fixed-precision numbers from trusted input--- since an attacker could easily fill up the memory of the target--- system by specifying a scientific number with a big exponent like--- @1e1000000000@.-instance HasResolution a => FromJSON (Fixed a) where-    parseJSON = withScientific "Fixed" $ pure . realToFrac-    {-# INLINE parseJSON #-}--instance ToJSON Int where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.intDec-    {-# INLINE toEncoding #-}--instance FromJSON Int where-    parseJSON = parseIntegral "Int"-    {-# INLINE parseJSON #-}--instance ToJSON Integer where-    toJSON = Number . fromInteger-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.integerDec-    {-# INLINE toEncoding #-}---- | /WARNING:/ Only parse Integers from trusted input since an--- attacker could easily fill up the memory of the target system by--- specifying a scientific number with a big exponent like--- @1e1000000000@.-instance FromJSON Integer where-    parseJSON = withScientific "Integral" $ pure . truncate-    {-# INLINE parseJSON #-}--instance ToJSON Natural where-    toJSON = toJSON . toInteger-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . toInteger-    {-# INLINE toEncoding #-}--instance FromJSON Natural where-    parseJSON = withScientific "Natural" $ \s ->-      if Scientific.coefficient s < 0-        then fail $ "Expected a Natural number but got the negative number: " <> show s-        else pure $ truncate s--instance ToJSON Int8 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.int8Dec-    {-# INLINE toEncoding #-}--instance FromJSON Int8 where-    parseJSON = parseIntegral "Int8"-    {-# INLINE parseJSON #-}--instance ToJSON Int16 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.int16Dec-    {-# INLINE toEncoding #-}--instance FromJSON Int16 where-    parseJSON = parseIntegral "Int16"-    {-# INLINE parseJSON #-}--instance ToJSON Int32 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.int32Dec-    {-# INLINE toEncoding #-}--instance FromJSON Int32 where-    parseJSON = parseIntegral "Int32"-    {-# INLINE parseJSON #-}--instance ToJSON Int64 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.int64Dec-    {-# INLINE toEncoding #-}--instance FromJSON Int64 where-    parseJSON = parseIntegral "Int64"-    {-# INLINE parseJSON #-}--instance ToJSON Word where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.wordDec-    {-# INLINE toEncoding #-}--instance FromJSON Word where-    parseJSON = parseIntegral "Word"-    {-# INLINE parseJSON #-}--instance ToJSON Word8 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.word8Dec-    {-# INLINE toEncoding #-}--instance FromJSON Word8 where-    parseJSON = parseIntegral "Word8"-    {-# INLINE parseJSON #-}--instance ToJSON Word16 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.word16Dec-    {-# INLINE toEncoding #-}--instance FromJSON Word16 where-    parseJSON = parseIntegral "Word16"-    {-# INLINE parseJSON #-}--instance ToJSON Word32 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.word32Dec-    {-# INLINE toEncoding #-}--instance FromJSON Word32 where-    parseJSON = parseIntegral "Word32"-    {-# INLINE parseJSON #-}--instance ToJSON Word64 where-    toJSON = Number . fromIntegral-    {-# INLINE toJSON #-}--    toEncoding = Encoding . B.word64Dec-    {-# INLINE toEncoding #-}--instance FromJSON Word64 where-    parseJSON = parseIntegral "Word64"-    {-# INLINE parseJSON #-}--instance ToJSON Text where-    toJSON = String-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.text-    {-# INLINE toEncoding #-}--instance FromJSON Text where-    parseJSON = withText "Text" pure-    {-# INLINE parseJSON #-}--instance ToJSON LT.Text where-    toJSON = String . LT.toStrict-    {-# INLINE toJSON #-}--    toEncoding t = Encoding $-      B.char7 '"' <>-      LT.foldrChunks (\x xs -> E.unquoted x <> xs) (B.char7 '"') t-    {-# INLINE toEncoding #-}--instance FromJSON LT.Text where-    parseJSON = withText "Lazy Text" $ pure . LT.fromStrict-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (NonEmpty a) where-    toJSON = toJSON . toList-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . toList-    {-# INLINE toEncoding #-}--instance (FromJSON a) => FromJSON (NonEmpty a) where-    parseJSON = withArray "NonEmpty a" $-        (>>= ne) . Tr.sequence . zipWith parseIndexedJSON [0..] . V.toList-      where-        ne []     = fail "Expected a NonEmpty but got an empty list"-        ne (x:xs) = pure (x :| xs)--instance OVERLAPPABLE_ (ToJSON a) => ToJSON [a] where-    toJSON = Array . V.fromList . map toJSON-    {-# INLINE toJSON #-}--    toEncoding xs = list xs-    {-# INLINE toEncoding #-}--instance OVERLAPPABLE_ (FromJSON a) => FromJSON [a] where-    parseJSON = withArray "[a]" $ Tr.sequence .-                zipWith parseIndexedJSON [0..] . V.toList-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (Seq.Seq a) where-    toJSON = toJSON . toList-    {-# INLINE toJSON #-}--    toEncoding = foldable-    {-# INLINE toEncoding #-}--instance (FromJSON a) => FromJSON (Seq.Seq a) where-    parseJSON = withArray "Seq a" $-      fmap Seq.fromList .-      Tr.sequence . zipWith parseIndexedJSON [0..] . V.toList-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (Vector a) where-    toJSON = Array . V.map toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeVector-    {-# INLINE toEncoding #-}--encodeVector :: (ToJSON a, VG.Vector v a) => v a -> Encoding-encodeVector xs-  | VG.null xs = E.emptyArray_-  | otherwise  = Encoding $-                 B.char7 '[' <> builder (VG.unsafeHead xs) <>-                 VG.foldr go (B.char7 ']') (VG.unsafeTail xs)-    where go v b = B.char7 ',' <> builder v <> b-{-# INLINE encodeVector #-}--instance (FromJSON a) => FromJSON (Vector a) where-    parseJSON = withArray "Vector a" $ V.mapM (uncurry parseIndexedJSON) .-                V.indexed-    {-# INLINE parseJSON #-}--vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value-vectorToJSON = Array . V.map toJSON . V.convert-{-# INLINE vectorToJSON #-}--vectorParseJSON :: (FromJSON a, VG.Vector w a) => String -> Value -> Parser (w a)-vectorParseJSON s = withArray s $ fmap V.convert . V.mapM (uncurry parseIndexedJSON) . V.indexed-{-# INLINE vectorParseJSON #-}--instance (Storable a, ToJSON a) => ToJSON (VS.Vector a) where-    toJSON = vectorToJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeVector-    {-# INLINE toEncoding #-}--instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where-    parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"--instance (VP.Prim a, ToJSON a) => ToJSON (VP.Vector a) where-    toJSON = vectorToJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeVector-    {-# INLINE toEncoding #-}--instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where-    parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"-    {-# INLINE parseJSON #-}--instance (VG.Vector VU.Vector a, ToJSON a) => ToJSON (VU.Vector a) where-    toJSON = vectorToJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeVector-    {-# INLINE toEncoding #-}--instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where-    parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (Set.Set a) where-    toJSON = toJSON . Set.toList-    {-# INLINE toJSON #-}--    toEncoding = encodeSet Set.minView Set.foldr-    {-# INLINE toEncoding #-}--instance (Ord a, FromJSON a) => FromJSON (Set.Set a) where-    parseJSON = fmap Set.fromList . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (HashSet.HashSet a) where-    toJSON = toJSON . HashSet.toList-    {-# INLINE toJSON #-}--    toEncoding = foldable-    {-# INLINE toEncoding #-}--instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where-    parseJSON = fmap HashSet.fromList . parseJSON-    {-# INLINE parseJSON #-}--instance ToJSON IntSet.IntSet where-    toJSON = toJSON . IntSet.toList-    {-# INLINE toJSON #-}--    toEncoding = encodeSet IntSet.minView IntSet.foldr-    {-# INLINE toEncoding #-}--encodeSet :: (ToJSON a) =>-             (s -> Maybe (a, s))-          -> ((a -> B.Builder -> B.Builder) -> B.Builder -> s -> B.Builder)-          -> s -> Encoding-encodeSet minView foldr xs =-    case minView xs of-      Nothing     -> E.emptyArray_-      Just (m,ys) -> Encoding $-                     B.char7 '[' <> builder m <> foldr go (B.char7 ']') ys-        where go v b = B.char7 ',' <> builder v <> b-{-# INLINE encodeSet #-}--instance FromJSON IntSet.IntSet where-    parseJSON = fmap IntSet.fromList . parseJSON-    {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (IntMap.IntMap a) where-    toJSON = toJSON . IntMap.toList-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . IntMap.toList-    {-# INLINE toEncoding #-}--instance FromJSON a => FromJSON (IntMap.IntMap a) where-    parseJSON = fmap IntMap.fromList . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (M.Map Text v) where-    toJSON = Object . M.foldrWithKey (\k -> H.insert k . toJSON) H.empty-    {-# INLINE toJSON #-}--    toEncoding = encodeMap M.minViewWithKey M.foldrWithKey-    {-# INLINE toEncoding #-}--encodeMap :: (ToJSON k, ToJSON v) =>-             (m -> Maybe ((k,v), m))-          -> ((k -> v -> B.Builder -> B.Builder) -> B.Builder -> m -> B.Builder)-          -> m -> Encoding-encodeMap minViewWithKey foldrWithKey xs =-    case minViewWithKey xs of-      Nothing         -> E.emptyObject_-      Just ((k,v),ys) -> Encoding $-                         B.char7 '{' <> encodeKV k v <>-                         foldrWithKey go (B.char7 '}') ys-  where go k v b = B.char7 ',' <> encodeKV k v <> b-{-# INLINE encodeMap #-}--encodeWithKey :: (ToJSON k, ToJSON v) =>-                 ((k -> v -> Series -> Series) -> Series -> m -> Series)-              -> m -> Encoding-encodeWithKey foldrWithKey = brackets '{' '}' . foldrWithKey go mempty-  where go k v c = Value (Encoding $ encodeKV k v) <> c-{-# INLINE encodeWithKey #-}--encodeKV :: (ToJSON k, ToJSON v) => k -> v -> B.Builder-encodeKV k v = builder k <> B.char7 ':' <> builder v-{-# INLINE encodeKV #-}--instance (FromJSON v) => FromJSON (M.Map Text v) where-    parseJSON = withObject "Map Text a" $-                  fmap (H.foldrWithKey M.insert M.empty) . H.traverseWithKey (\k v -> parseJSON v <?> Key k)--instance (ToJSON v) => ToJSON (M.Map LT.Text v) where-    toJSON = Object . mapHashKeyVal LT.toStrict toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeMap M.minViewWithKey M.foldrWithKey-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (M.Map LT.Text v) where-    parseJSON = fmap (hashMapKey LT.fromStrict) . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (M.Map String v) where-    toJSON = Object . mapHashKeyVal pack toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeMap M.minViewWithKey M.foldrWithKey-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (M.Map String v) where-    parseJSON = fmap (hashMapKey unpack) . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (H.HashMap Text v) where-    toJSON = Object . H.map toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeWithKey H.foldrWithKey-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (H.HashMap Text v) where-    parseJSON = withObject "HashMap Text a" $ H.traverseWithKey (\k v -> parseJSON v <?> Key k)-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (H.HashMap LT.Text v) where-    toJSON = Object . mapKeyVal LT.toStrict toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeWithKey H.foldrWithKey-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (H.HashMap LT.Text v) where-    parseJSON = fmap (mapKey LT.fromStrict) . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (H.HashMap String v) where-    toJSON = Object . mapKeyVal pack toJSON-    {-# INLINE toJSON #-}--    toEncoding = encodeWithKey H.foldrWithKey-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (H.HashMap String v) where-    parseJSON = fmap (mapKey unpack) . parseJSON-    {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (Tree.Tree v) where-    toJSON (Tree.Node root branches) = toJSON (root,branches)-    {-# INLINE toJSON #-}--    toEncoding (Tree.Node root branches) = toEncoding (root,branches)-    {-# INLINE toEncoding #-}--instance (FromJSON v) => FromJSON (Tree.Tree v) where-    parseJSON j = uncurry Tree.Node <$> parseJSON j-    {-# INLINE parseJSON #-}--instance ToJSON Value where-    toJSON a = a-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.encodeToBuilder-    {-# INLINE toEncoding #-}--instance FromJSON Value where-    parseJSON a = pure a-    {-# INLINE parseJSON #-}--instance ToJSON DotNetTime where-    toJSON = toJSON . dotNetTime--    toEncoding = toEncoding . dotNetTime--dotNetTime :: DotNetTime -> String-dotNetTime (DotNetTime t) = secs ++ formatMillis t ++ ")/"-  where secs  = formatTime defaultTimeLocale "/Date(%s" t--instance FromJSON DotNetTime where-    parseJSON = withText "DotNetTime" $ \t ->-        let (s,m) = T.splitAt (T.length t - 5) t-            t'    = T.concat [s,".",m]-        in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of-             Just d -> pure (DotNetTime d)-             _      -> fail "could not parse .NET time"-    {-# INLINE parseJSON #-}--instance ToJSON Day where-    toJSON       = stringEncoding-    toEncoding z = Encoding (E.quote $ E.day z)--instance FromJSON Day where-    parseJSON = withText "Day" (Time.run Time.day)--instance ToJSON TimeOfDay where-    toJSON       = stringEncoding-    toEncoding z = Encoding (E.quote $ E.timeOfDay z)--instance FromJSON TimeOfDay where-    parseJSON = withText "TimeOfDay" (Time.run Time.timeOfDay)--instance ToJSON LocalTime where-    toJSON       = stringEncoding-    toEncoding z = Encoding (E.quote $ E.localTime z)--instance FromJSON LocalTime where-    parseJSON = withText "LocalTime" (Time.run Time.localTime)--instance ToJSON ZonedTime where-    toJSON = stringEncoding--    toEncoding z = Encoding (E.quote $ E.zonedTime z)--formatMillis :: (FormatTime t) => t -> String-formatMillis = take 3 . formatTime defaultTimeLocale "%q"--instance FromJSON ZonedTime where-    parseJSON = withText "ZonedTime" (Time.run Time.zonedTime)--instance ToJSON UTCTime where-    toJSON = stringEncoding--    toEncoding t = Encoding (E.quote $ E.utcTime t)---- | Encode something to a JSON string.-stringEncoding :: (ToJSON a) => a -> Value-stringEncoding = String . T.dropAround (== '"') . T.decodeLatin1 . L.toStrict . encode-{-# INLINE stringEncoding #-}--instance FromJSON UTCTime where-    parseJSON = withText "UTCTime" (Time.run Time.utcTime)--instance ToJSON NominalDiffTime where-    toJSON = Number . realToFrac-    {-# INLINE toJSON #-}--    toEncoding = Encoding . E.number . realToFrac-    {-# INLINE toEncoding #-}---- | /WARNING:/ Only parse lengths of time from trusted input--- since an attacker could easily fill up the memory of the target--- system by specifying a scientific number with a big exponent like--- @1e1000000000@.-instance FromJSON NominalDiffTime where-    parseJSON = withScientific "NominalDiffTime" $ pure . realToFrac-    {-# INLINE parseJSON #-}--parseJSONElemAtIndex :: FromJSON a => Int -> Vector Value -> Parser a-parseJSONElemAtIndex idx ary = parseJSON (V.unsafeIndex ary idx) <?> Index idx--tuple :: B.Builder -> Encoding-tuple b = Encoding (B.char7 '[' <> b <> B.char7 ']')-{-# INLINE tuple #-}--(>*<) :: B.Builder -> B.Builder -> B.Builder-a >*< b = a <> B.char7 ',' <> b-{-# INLINE (>*<) #-}-infixr 6 >*<--instance (ToJSON a, ToJSON b) => ToJSON (a,b) where-    toJSON (a,b) = Array $ V.create $ do-                     mv <- VM.unsafeNew 2-                     VM.unsafeWrite mv 0 (toJSON a)-                     VM.unsafeWrite mv 1 (toJSON b)-                     return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b) = tuple $-      builder a >*< builder b-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b) => FromJSON (a,b) where-    parseJSON = withArray "(a,b)" $ \ab ->-        let n = V.length ab-        in if n == 2-             then (,) <$> parseJSONElemAtIndex 0 ab-                      <*> parseJSONElemAtIndex 1 ab-             else fail $ "cannot unpack array of length " ++-                         show n ++ " into a pair"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON (a,b,c) where-    toJSON (a,b,c) = Array $ V.create $ do-                       mv <- VM.unsafeNew 3-                       VM.unsafeWrite mv 0 (toJSON a)-                       VM.unsafeWrite mv 1 (toJSON b)-                       VM.unsafeWrite mv 2 (toJSON c)-                       return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c) = tuple $-      builder a >*<-      builder b >*<-      builder c-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON (a,b,c) where-    parseJSON = withArray "(a,b,c)" $ \abc ->-        let n = V.length abc-        in if n == 3-             then (,,) <$> parseJSONElemAtIndex 0 abc-                       <*> parseJSONElemAtIndex 1 abc-                       <*> parseJSONElemAtIndex 2 abc-             else fail $ "cannot unpack array of length " ++-                          show n ++ " into a 3-tuple"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON (a,b,c,d) where-    toJSON (a,b,c,d) = Array $ V.create $ do-                         mv <- VM.unsafeNew 4-                         VM.unsafeWrite mv 0 (toJSON a)-                         VM.unsafeWrite mv 1 (toJSON b)-                         VM.unsafeWrite mv 2 (toJSON c)-                         VM.unsafeWrite mv 3 (toJSON d)-                         return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) =>-         FromJSON (a,b,c,d) where-    parseJSON = withArray "(a,b,c,d)" $ \abcd ->-        let n = V.length abcd-        in if n == 4-             then (,,,) <$> parseJSONElemAtIndex 0 abcd-                        <*> parseJSONElemAtIndex 1 abcd-                        <*> parseJSONElemAtIndex 2 abcd-                        <*> parseJSONElemAtIndex 3 abcd-             else fail $ "cannot unpack array of length " ++-                         show n ++ " into a 4-tuple"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) =>-         ToJSON (a,b,c,d,e) where-    toJSON (a,b,c,d,e) = Array $ V.create $ do-                           mv <- VM.unsafeNew 5-                           VM.unsafeWrite mv 0 (toJSON a)-                           VM.unsafeWrite mv 1 (toJSON b)-                           VM.unsafeWrite mv 2 (toJSON c)-                           VM.unsafeWrite mv 3 (toJSON d)-                           VM.unsafeWrite mv 4 (toJSON e)-                           return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e) =>-         FromJSON (a,b,c,d,e) where-    parseJSON = withArray "(a,b,c,d,e)" $ \abcde ->-        let n = V.length abcde-        in if n == 5-             then (,,,,) <$> parseJSONElemAtIndex 0 abcde-                         <*> parseJSONElemAtIndex 1 abcde-                         <*> parseJSONElemAtIndex 2 abcde-                         <*> parseJSONElemAtIndex 3 abcde-                         <*> parseJSONElemAtIndex 4 abcde-             else fail $ "cannot unpack array of length " ++-                         show n ++ " into a 5-tuple"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) =>-         ToJSON (a,b,c,d,e,f) where-    toJSON (a,b,c,d,e,f) = Array $ V.create $ do-                             mv <- VM.unsafeNew 6-                             VM.unsafeWrite mv 0 (toJSON a)-                             VM.unsafeWrite mv 1 (toJSON b)-                             VM.unsafeWrite mv 2 (toJSON c)-                             VM.unsafeWrite mv 3 (toJSON d)-                             VM.unsafeWrite mv 4 (toJSON e)-                             VM.unsafeWrite mv 5 (toJSON f)-                             return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f) => FromJSON (a,b,c,d,e,f) where-    parseJSON = withArray "(a,b,c,d,e,f)" $ \abcdef ->-        let n = V.length abcdef-        in if n == 6-             then (,,,,,) <$> parseJSONElemAtIndex 0 abcdef-                          <*> parseJSONElemAtIndex 1 abcdef-                          <*> parseJSONElemAtIndex 2 abcdef-                          <*> parseJSONElemAtIndex 3 abcdef-                          <*> parseJSONElemAtIndex 4 abcdef-                          <*> parseJSONElemAtIndex 5 abcdef-             else fail $ "cannot unpack array of length " ++-                         show n ++ " into a 6-tuple"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g) => ToJSON (a,b,c,d,e,f,g) where-    toJSON (a,b,c,d,e,f,g) = Array $ V.create $ do-                               mv <- VM.unsafeNew 7-                               VM.unsafeWrite mv 0 (toJSON a)-                               VM.unsafeWrite mv 1 (toJSON b)-                               VM.unsafeWrite mv 2 (toJSON c)-                               VM.unsafeWrite mv 3 (toJSON d)-                               VM.unsafeWrite mv 4 (toJSON e)-                               VM.unsafeWrite mv 5 (toJSON f)-                               VM.unsafeWrite mv 6 (toJSON g)-                               return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g) => FromJSON (a,b,c,d,e,f,g) where-    parseJSON = withArray "(a,b,c,d,e,f,g)" $ \abcdefg ->-        let n = V.length abcdefg-        in if n == 7-             then (,,,,,,) <$> parseJSONElemAtIndex 0 abcdefg-                           <*> parseJSONElemAtIndex 1 abcdefg-                           <*> parseJSONElemAtIndex 2 abcdefg-                           <*> parseJSONElemAtIndex 3 abcdefg-                           <*> parseJSONElemAtIndex 4 abcdefg-                           <*> parseJSONElemAtIndex 5 abcdefg-                           <*> parseJSONElemAtIndex 6 abcdefg-             else fail $ "cannot unpack array of length " ++-                         show n ++ " into a 7-tuple"-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h) => ToJSON (a,b,c,d,e,f,g,h) where-    toJSON (a,b,c,d,e,f,g,h) = Array $ V.create $ do-      mv <- VM.unsafeNew 8-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h) =>-         FromJSON (a,b,c,d,e,f,g,h) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h)" $ \ary ->-        let n = V.length ary-        in if n /= 8-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into an 8-tuple"-           else (,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i) => ToJSON (a,b,c,d,e,f,g,h,i) where-    toJSON (a,b,c,d,e,f,g,h,i) = Array $ V.create $ do-      mv <- VM.unsafeNew 9-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i) =>-         FromJSON (a,b,c,d,e,f,g,h,i) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i)" $ \ary ->-        let n = V.length ary-        in if n /= 9-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 9-tuple"-           else (,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j) where-    toJSON (a,b,c,d,e,f,g,h,i,j) = Array $ V.create $ do-      mv <- VM.unsafeNew 10-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j)" $ \ary ->-        let n = V.length ary-        in if n /= 10-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 10-tuple"-           else (,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j,k) where-    toJSON (a,b,c,d,e,f,g,h,i,j,k) = Array $ V.create $ do-      mv <- VM.unsafeNew 11-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      VM.unsafeWrite mv 10 (toJSON k)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j,k) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j >*<-      builder k-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j,-          FromJSON k) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j,k) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j,k)" $ \ary ->-        let n = V.length ary-        in if n /= 11-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into an 11-tuple"-           else (,,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-                <*> parseJSONElemAtIndex 10 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j,k,l) where-    toJSON (a,b,c,d,e,f,g,h,i,j,k,l) = Array $ V.create $ do-      mv <- VM.unsafeNew 12-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      VM.unsafeWrite mv 10 (toJSON k)-      VM.unsafeWrite mv 11 (toJSON l)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j,k,l) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j >*<-      builder k >*<-      builder l-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j,-          FromJSON k, FromJSON l) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j,k,l) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j,k,l)" $ \ary ->-        let n = V.length ary-        in if n /= 12-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 12-tuple"-           else (,,,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-                <*> parseJSONElemAtIndex 10 ary-                <*> parseJSONElemAtIndex 11 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l,-          ToJSON m) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j,k,l,m) where-    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m) = Array $ V.create $ do-      mv <- VM.unsafeNew 13-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      VM.unsafeWrite mv 10 (toJSON k)-      VM.unsafeWrite mv 11 (toJSON l)-      VM.unsafeWrite mv 12 (toJSON m)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j,k,l,m) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j >*<-      builder k >*<-      builder l >*<-      builder m-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j,-          FromJSON k, FromJSON l, FromJSON m) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j,k,l,m) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j,k,l,m)" $ \ary ->-        let n = V.length ary-        in if n /= 13-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 13-tuple"-           else (,,,,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-                <*> parseJSONElemAtIndex 10 ary-                <*> parseJSONElemAtIndex 11 ary-                <*> parseJSONElemAtIndex 12 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l,-          ToJSON m, ToJSON n) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where-    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n) = Array $ V.create $ do-      mv <- VM.unsafeNew 14-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      VM.unsafeWrite mv 10 (toJSON k)-      VM.unsafeWrite mv 11 (toJSON l)-      VM.unsafeWrite mv 12 (toJSON m)-      VM.unsafeWrite mv 13 (toJSON n)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j,k,l,m,n) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j >*<-      builder k >*<-      builder l >*<-      builder m >*<-      builder n-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j,-          FromJSON k, FromJSON l, FromJSON m, FromJSON n) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j,k,l,m,n)" $ \ary ->-        let n = V.length ary-        in if n /= 14-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 14-tuple"-           else (,,,,,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-                <*> parseJSONElemAtIndex 10 ary-                <*> parseJSONElemAtIndex 11 ary-                <*> parseJSONElemAtIndex 12 ary-                <*> parseJSONElemAtIndex 13 ary-    {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f,-          ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l,-          ToJSON m, ToJSON n, ToJSON o) =>-         ToJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where-    toJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) = Array $ V.create $ do-      mv <- VM.unsafeNew 15-      VM.unsafeWrite mv 0 (toJSON a)-      VM.unsafeWrite mv 1 (toJSON b)-      VM.unsafeWrite mv 2 (toJSON c)-      VM.unsafeWrite mv 3 (toJSON d)-      VM.unsafeWrite mv 4 (toJSON e)-      VM.unsafeWrite mv 5 (toJSON f)-      VM.unsafeWrite mv 6 (toJSON g)-      VM.unsafeWrite mv 7 (toJSON h)-      VM.unsafeWrite mv 8 (toJSON i)-      VM.unsafeWrite mv 9 (toJSON j)-      VM.unsafeWrite mv 10 (toJSON k)-      VM.unsafeWrite mv 11 (toJSON l)-      VM.unsafeWrite mv 12 (toJSON m)-      VM.unsafeWrite mv 13 (toJSON n)-      VM.unsafeWrite mv 14 (toJSON o)-      return mv-    {-# INLINE toJSON #-}--    toEncoding (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) = tuple $-      builder a >*<-      builder b >*<-      builder c >*<-      builder d >*<-      builder e >*<-      builder f >*<-      builder g >*<-      builder h >*<-      builder i >*<-      builder j >*<-      builder k >*<-      builder l >*<-      builder m >*<-      builder n >*<-      builder o-    {-# INLINE toEncoding #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e,-          FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j,-          FromJSON k, FromJSON l, FromJSON m, FromJSON n, FromJSON o) =>-         FromJSON (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where-    parseJSON = withArray "(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)" $ \ary ->-        let n = V.length ary-        in if n /= 15-           then fail $ "cannot unpack array of length " ++-                       show n ++ " into a 15-tuple"-           else (,,,,,,,,,,,,,,)-                <$> parseJSONElemAtIndex 0 ary-                <*> parseJSONElemAtIndex 1 ary-                <*> parseJSONElemAtIndex 2 ary-                <*> parseJSONElemAtIndex 3 ary-                <*> parseJSONElemAtIndex 4 ary-                <*> parseJSONElemAtIndex 5 ary-                <*> parseJSONElemAtIndex 6 ary-                <*> parseJSONElemAtIndex 7 ary-                <*> parseJSONElemAtIndex 8 ary-                <*> parseJSONElemAtIndex 9 ary-                <*> parseJSONElemAtIndex 10 ary-                <*> parseJSONElemAtIndex 11 ary-                <*> parseJSONElemAtIndex 12 ary-                <*> parseJSONElemAtIndex 13 ary-                <*> parseJSONElemAtIndex 14 ary-    {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (Dual a) where-    toJSON = toJSON . getDual-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . getDual-    {-# INLINE toEncoding #-}--instance FromJSON a => FromJSON (Dual a) where-    parseJSON = fmap Dual . parseJSON-    {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (First a) where-    toJSON = toJSON . getFirst-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . getFirst-    {-# INLINE toEncoding #-}--instance FromJSON a => FromJSON (First a) where-    parseJSON = fmap First . parseJSON-    {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (Last a) where-    toJSON = toJSON . getLast-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . getLast-    {-# INLINE toEncoding #-}--instance FromJSON a => FromJSON (Last a) where-    parseJSON = fmap Last . parseJSON-    {-# INLINE parseJSON #-}--instance ToJSON Version where-    toJSON = toJSON . showVersion-    {-# INLINE toJSON #-}--    toEncoding = toEncoding . showVersion-    {-# INLINE toEncoding #-}--instance FromJSON Version where-    {-# INLINE parseJSON #-}-    parseJSON = withText "Version" $ go . readP_to_S parseVersion . unpack-      where-        go [(v,[])] = return v-        go (_ : xs) = go xs-        go _        = fail $ "could not parse Version"--instance ToJSON (Proxy a) where-    toJSON _ = Null-    {-# INLINE toJSON #-}--    toEncoding _ = Encoding E.null_-    {-# INLINE toEncoding #-}--instance FromJSON (Proxy a) where-    {-# INLINE parseJSON #-}-    parseJSON Null = pure Proxy-    parseJSON v    = typeMismatch "Proxy" v--instance ToJSON b => ToJSON (Tagged a b) where-    toJSON (Tagged x) = toJSON x-    {-# INLINE toJSON #-}--    toEncoding (Tagged x) = toEncoding x-    {-# INLINE toEncoding #-}--instance FromJSON b => FromJSON (Tagged a b) where-    {-# INLINE parseJSON #-}-    parseJSON = fmap Tagged . parseJSON--instance ToJSON a => ToJSON (Const a b) where-    toJSON (Const x) = toJSON x-    {-# INLINE toJSON #-}--    toEncoding (Const x) = toEncoding x-    {-# INLINE toEncoding #-}--instance FromJSON a => FromJSON (Const a b) where-    {-# INLINE parseJSON #-}-    parseJSON = fmap Const . parseJSON---- | @withObject expected f value@ applies @f@ to the 'Object' when @value@ is an @Object@---   and fails using @'typeMismatch' expected@ otherwise.-withObject :: String -> (Object -> Parser a) -> Value -> Parser a-withObject _        f (Object obj) = f obj-withObject expected _ v            = typeMismatch expected v-{-# INLINE withObject #-}---- | @withText expected f value@ applies @f@ to the 'Text' when @value@ is a @String@---   and fails using @'typeMismatch' expected@ otherwise.-withText :: String -> (Text -> Parser a) -> Value -> Parser a-withText _        f (String txt) = f txt-withText expected _ v            = typeMismatch expected v-{-# INLINE withText #-}---- | @withArray expected f value@ applies @f@ to the 'Array' when @value@ is an @Array@---   and fails using @'typeMismatch' expected@ otherwise.-withArray :: String -> (Array -> Parser a) -> Value -> Parser a-withArray _        f (Array arr) = f arr-withArray expected _ v           = typeMismatch expected v-{-# INLINE withArray #-}---- | @withNumber expected f value@ applies @f@ to the 'Number' when @value@ is a 'Number'.---   and fails using @'typeMismatch' expected@ otherwise.-withNumber :: String -> (Number -> Parser a) -> Value -> Parser a-withNumber expected f = withScientific expected (f . scientificToNumber)-{-# INLINE withNumber #-}-{-# DEPRECATED withNumber "Use withScientific instead" #-}---- | @withScientific expected f value@ applies @f@ to the 'Scientific' number when @value@ is a 'Number'.---   and fails using @'typeMismatch' expected@ otherwise.-withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a-withScientific _        f (Number scientific) = f scientific-withScientific expected _ v                   = typeMismatch expected v-{-# INLINE withScientific #-}---- | @withBool expected f value@ applies @f@ to the 'Bool' when @value@ is a @Bool@---   and fails using @'typeMismatch' expected@ otherwise.-withBool :: String -> (Bool -> Parser a) -> Value -> Parser a-withBool _        f (Bool arr) = f arr-withBool expected _ v          = typeMismatch expected v-{-# INLINE withBool #-}--instance KeyValue Pair where-    name .= value = (name, toJSON value)-    {-# INLINE (.=) #-}--instance KeyValue Series where-    name .= value = Value . Encoding $-                    E.text name <> B.char7 ':' <> builder value-    {-# INLINE (.=) #-}---- | Convert a value from JSON, failing if the types do not match.-fromJSON :: (FromJSON a) => Value -> Result a-fromJSON = parse parseJSON-{-# INLINE fromJSON #-}---- | Convert a value from JSON, failing if the types do not match.-ifromJSON :: (FromJSON a) => Value -> IResult a-ifromJSON = iparse parseJSON-{-# INLINE ifromJSON #-}---- | Retrieve the value associated with the given key of an 'Object'.--- The result is 'empty' if the key is not present or the value cannot--- be converted to the desired type.------ This accessor is appropriate if the key and value /must/ be present--- in an object for it to be valid.  If the key and value are--- optional, use '.:?' instead.-(.:) :: (FromJSON a) => Object -> Text -> Parser a-obj .: key = case H.lookup key obj of-               Nothing -> fail $ "key " ++ show key ++ " not present"-               Just v  -> modifyFailure addKeyName-                        $ parseJSON v <?> Key key-  where-    addKeyName = (("failed to parse field " <> unpack key <> ": ") <>)-{-# INLINE (.:) #-}---- | Retrieve the value associated with the given key of an 'Object'.--- The result is 'Nothing' if the key is not present, or 'empty' if--- the value cannot be converted to the desired type.------ This accessor is most useful if the key and value can be absent--- from an object without affecting its validity.  If the key and--- value are mandatory, use '.:' instead.-(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)-obj .:? key = case H.lookup key obj of-               Nothing -> pure Nothing-               Just v  -> modifyFailure addKeyName-                        $ parseJSON v <?> Key key-  where-    addKeyName = (("failed to parse field " <> unpack key <> ": ") <>)-{-# INLINE (.:?) #-}---- | Like '.:?', but the resulting parser will fail,--- if the key is present but is 'Null'.-(.:!) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)-obj .:! key = case H.lookup key obj of-               Nothing -> pure Nothing-               Just v  -> modifyFailure addKeyName-                        $ Just <$> parseJSON v <?> Key key-  where-    addKeyName = (("failed to parse field " <> unpack key <> ": ") <>)-{-# INLINE (.:!) #-}---- | Helper for use in combination with '.:?' to provide default--- values for optional JSON object fields.------ This combinator is most useful if the key and value can be absent--- from an object without affecting its validity and we know a default--- value to assign in that case.  If the key and value are mandatory,--- use '.:' instead.------ Example usage:------ @ v1 <- o '.:?' \"opt_field_with_dfl\" .!= \"default_val\"--- v2 <- o '.:'  \"mandatory_field\"--- v3 <- o '.:?' \"opt_field2\"--- @-(.!=) :: Parser (Maybe a) -> a -> Parser a-pmval .!= val = fromMaybe val <$> pmval-{-# INLINE (.!=) #-}--realFloatToJSON :: RealFloat a => a -> Value-realFloatToJSON d-    | isNaN d || isInfinite d = Null-    | otherwise = Number $ Scientific.fromFloatDigits d-{-# INLINE realFloatToJSON #-}--realFloatToEncoding :: RealFloat a => a -> Encoding-realFloatToEncoding d-    | isNaN d || isInfinite d = Encoding E.null_-    | otherwise               = toEncoding (Scientific.fromFloatDigits d)-{-# INLINE realFloatToEncoding #-}--scientificToNumber :: Scientific -> Number-scientificToNumber s-    | e < 0     = D $ Scientific.toRealFloat s-    | otherwise = I $ c * 10 ^ e-  where-    e = Scientific.base10Exponent s-    c = Scientific.coefficient s-{-# INLINE scientificToNumber #-}--parseRealFloat :: RealFloat a => String -> Value -> Parser a-parseRealFloat _        (Number s) = pure $ Scientific.toRealFloat s-parseRealFloat _        Null       = pure (0/0)-parseRealFloat expected v          = typeMismatch expected v-{-# INLINE parseRealFloat #-}--parseIntegral :: Integral a => String -> Value -> Parser a-parseIntegral expected = withScientific expected $ pure . truncate-{-# INLINE parseIntegral #-}
Data/Aeson/Types/Internal.hs view
@@ -1,5 +1,8 @@-{-# LANGUAGE CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving, Rank2Types,-    RecordWildCards #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE RecordWildCards #-} #if __GLASGOW_HASKELL__ >= 800 -- a) THQ works on cross-compilers and unregisterised GHCs -- b) may make compilation faster as no dynamic loading is ever needed (not sure about this)@@ -24,14 +27,12 @@     (     -- * Core JSON types       Value(..)-    , Encoding(..)-    , unsafeToEncoding-    , Series(..)     , Array     , emptyArray, isEmptyArray     , Pair     , Object     , emptyObject+     -- * Type conversion     , Parser     , Result(..)@@ -62,36 +63,32 @@     , DotNetTime(..)     ) where +import Prelude ()+import Prelude.Compat++import Control.Applicative (Alternative(..)) import Control.Arrow (first)-import Control.Applicative import Control.DeepSeq (NFData(..)) import Control.Monad (MonadPlus(..), ap)-import qualified Control.Monad.Fail as Fail-import Data.ByteString.Builder (Builder, char7, toLazyByteString) import Data.Char (isLower, isUpper, toLower, isAlpha, isAlphaNum) import Data.Data (Data) import Data.Foldable (foldl') import Data.HashMap.Strict (HashMap) import Data.Hashable (Hashable(..))-import Data.Semigroup (Semigroup((<>))) import Data.Scientific (Scientific)+import Data.Semigroup (Semigroup((<>))) import Data.String (IsString(..)) import Data.Text (Text, pack, unpack) import Data.Time (UTCTime) import Data.Time.Format (FormatTime) import Data.Typeable (Typeable) import Data.Vector (Vector)+import qualified Control.Monad.Fail as Fail import qualified Data.HashMap.Strict as H import qualified Data.Scientific as S import qualified Data.Vector as V import qualified Language.Haskell.TH.Syntax as TH -#if !MIN_VERSION_base(4,8,0)-import Data.Foldable (Foldable(..))-import Data.Monoid (Monoid(..))-import Data.Traversable (Traversable(..))-#endif- #if !MIN_VERSION_unordered_containers(0,2,6) import Data.List (sort) #endif@@ -338,52 +335,6 @@            | Null              deriving (Eq, Read, Show, Typeable, Data) --- | An encoding of a JSON value.-newtype Encoding = Encoding {-      fromEncoding :: Builder-      -- ^ Acquire the underlying bytestring builder.-    } deriving (Semigroup,Monoid)---- | Make Encoding from Builder.------ Use with care! You have to make sure that the passed Builder--- is a valid JSON Encoding!-unsafeToEncoding :: Builder -> Encoding-unsafeToEncoding = Encoding--instance Show Encoding where-    show (Encoding e) = show (toLazyByteString e)--instance Eq Encoding where-    Encoding a == Encoding b = toLazyByteString a == toLazyByteString b--instance Ord Encoding where-    compare (Encoding a) (Encoding b) =-      compare (toLazyByteString a) (toLazyByteString b)---- | A series of values that, when encoded, should be separated by--- commas. Since 0.11.0.0, the '.=' operator is overloaded to create--- either @(Text, Value)@ or 'Series'. You can use Series when--- encoding directly to a bytestring builder as in the following--- example:------ > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)-data Series = Empty-            | Value Encoding-            deriving (Typeable)--instance Semigroup Series where-    Empty   <> a = a-    Value a <> b =-        Value $-        a <> case b of-               Empty   -> mempty-               Value c -> Encoding (char7 ',') <> c--instance Monoid Series where-    mempty  = Empty-    mappend = (<>)- -- | A newtype wrapper for 'UTCTime' that uses the same non-standard -- serialization format as Microsoft .NET, whose -- <https://msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx System.DateTime>@@ -482,7 +433,7 @@ -- | Annotate an error message with a -- <http://goessner.net/articles/JsonPath/ JSONPath> error location. formatError :: JSONPath -> String -> String-formatError path msg = "Error in " ++ (format "$" path) ++ ": " ++ msg+formatError path msg = "Error in " ++ format "$" path ++ ": " ++ msg   where     format :: String -> JSONPath -> String     format pfx []                = pfx@@ -601,6 +552,20 @@     -- by the encoded value of that field! If the constructor is not a     -- record the encoded constructor contents will be stored under     -- the 'contentsFieldName' field.+  | UntaggedValue+    -- ^ Constructor names won't be encoded. Instead only the contents of the+    -- constructor will be encoded as if the type had single constructor. JSON+    -- encodings have to be disjoint for decoding to work properly.+    --+    -- When decoding, constructors are tried in the order of definition. If some+    -- encodings overlap, the first one defined will succeed.+    --+    -- /Note:/ Nullary constructors are encoded as the string (using+    -- 'constructorTagModifier'). Having a nullary constructor alongside a+    -- single field constructor that encodes to a string leads to ambiguity.+    --+    -- /Note:/ Only the last error is kept when decoding, so in the case of+    -- mailformed JSON, only an error for the last constructor will be reported.   | ObjectWithSingleField     -- ^ A constructor will be encoded to an object with a single     -- field named after the constructor tag (modified by the
+ Data/Aeson/Types/ToJSON.hs view
@@ -0,0 +1,2689 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}++#if __GLASGOW_HASKELL__ >= 706+{-# LANGUAGE PolyKinds #-}+#endif++#include "overlapping-compat.h"++-- TODO: Drop this when we remove support for Data.Attoparsec.Number+{-# OPTIONS_GHC -fno-warn-deprecations #-}++module Data.Aeson.Types.ToJSON+    (+    -- * Core JSON classes+      ToJSON(..)+    -- * Liftings to unary and binary type constructors+    , ToJSON1(..)+    , toJSON1+    , toEncoding1+    , ToJSON2(..)+    , toJSON2+    , toEncoding2+    -- * Generic JSON classes+    , GToJSON(..)+    , GToEncoding(..)+    , ToArgs(..)+    , genericToJSON+    , genericToEncoding+    , genericLiftToJSON+    , genericLiftToEncoding+    -- * Classes and types for map keys+    , ToJSONKey(..)+    , ToJSONKeyFunction(..)+    , toJSONKeyText+    , contramapToJSONKeyFunction+    -- * Object key-value pairs+    , KeyValue(..)+    -- * Functions needed for documentation+    -- * Encoding functions+    , listEncoding+    , listValue+    ) where++import Prelude ()+import Prelude.Compat++import Control.Applicative (Const(..))+import Control.Monad.ST (ST)+import Data.Aeson.Encoding (Encoding, Encoding', Series, dict, emptyArray_)+import Data.Aeson.Encoding.Internal ((>*<), (><))+import Data.Aeson.Internal.Functions (mapHashKeyVal, mapKeyVal)+import Data.Aeson.Types.Generic (AllNullary, False, IsRecord(..), One, ProductSize, Tagged2(..), True, Zero, productSize)+import Data.Aeson.Types.Internal+import Data.Attoparsec.Number (Number(..))+import Data.Bits (unsafeShiftR)+import Data.DList (DList)+import Data.Fixed (Fixed, HasResolution)+import Data.Foldable (toList)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))+import Data.Functor.Product (Product(..))+import Data.Functor.Sum (Sum(..))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List (intersperse)+import Data.List.NonEmpty (NonEmpty(..))+import Data.Monoid ((<>), Dual(..), First(..), Last(..))+import Data.Proxy (Proxy(..))+import Data.Ratio (Ratio, denominator, numerator)+import Data.Scientific (Scientific)+import Data.Tagged (Tagged(..))+import Data.Text (Text, pack)+import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)+import Data.Time.Format (FormatTime, formatTime)+import Data.Time.Locale.Compat (defaultTimeLocale)+import Data.Vector (Vector)+import Data.Version (Version, showVersion)+import Data.Word (Word16, Word32, Word64, Word8)+import Foreign.Storable (Storable)+import GHC.Generics+import Numeric.Natural (Natural)+import qualified Data.Aeson.Encoding as E+import qualified Data.Aeson.Encoding.Internal as E (InArray, colon, comma, econcat, empty, retagEncoding, wrapObject)+import qualified Data.ByteString as S+import qualified Data.ByteString.Lazy as L+import qualified Data.DList as DList+import qualified Data.HashMap.Strict as H+import qualified Data.HashSet as HashSet+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M+import qualified Data.Scientific as Scientific+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as LT+import qualified Data.Tree as Tree+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Mutable as VM+import qualified Data.Vector.Primitive as VP+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Unboxed as VU++#if !(MIN_VERSION_bytestring(0,10,0))+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Marshal.Utils (copyBytes)+import Foreign.Ptr (plusPtr)+import qualified Data.ByteString.Internal as S+import qualified Data.ByteString.Lazy.Internal as L+#endif++toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value+toJSONPair a b = liftToJSON2 a (listValue a) b (listValue b)+{-# INLINE toJSONPair #-}++realFloatToJSON :: RealFloat a => a -> Value+realFloatToJSON d+    | isNaN d || isInfinite d = Null+    | otherwise = Number $ Scientific.fromFloatDigits d+{-# INLINE realFloatToJSON #-}++-------------------------------------------------------------------------------+-- Generics+-------------------------------------------------------------------------------++-- | Class of generic representation types that can be converted to+-- JSON.+class GToJSON arity f where+    -- | This method (applied to 'defaultOptions') is used as the+    -- default generic implementation of 'toJSON' (if the @arity@ is 'Zero')+    -- or 'liftToJSON' (if the @arity@ is 'One').+    gToJSON :: Options -> ToArgs Value arity a -> f a -> Value++-- | Class of generic representation types that can be converted to+-- a JSON 'Encoding'.+class GToEncoding arity f where+    -- | This method (applied to 'defaultOptions') can be used as the+    -- default generic implementation of 'toEncoding' (if the @arity@ is 'Zero')+    -- or 'liftToEncoding' (if the @arity@ is 'One').+    gToEncoding :: Options -> ToArgs Encoding arity a -> f a -> Encoding++-- | A 'ToArgs' value either stores nothing (for 'ToJSON') or it stores the two+-- function arguments that encode occurrences of the type parameter (for+-- 'ToJSON1').+data ToArgs res arity a where+    NoToArgs :: ToArgs res Zero a+    To1Args  :: (a -> res) -> ([a] -> res) -> ToArgs res One a++-- | A configurable generic JSON creator. This function applied to+-- 'defaultOptions' is used as the default for 'toJSON' when the type+-- is an instance of 'Generic'.+genericToJSON :: (Generic a, GToJSON Zero (Rep a))+              => Options -> a -> Value+genericToJSON opts = gToJSON opts NoToArgs . from++-- | A configurable generic JSON creator. This function applied to+-- 'defaultOptions' is used as the default for 'liftToJSON' when the type+-- is an instance of 'Generic1'.+genericLiftToJSON :: (Generic1 f, GToJSON One (Rep1 f))+                  => Options -> (a -> Value) -> ([a] -> Value)+                  -> f a -> Value+genericLiftToJSON opts tj tjl = gToJSON opts (To1Args tj tjl) . from1++-- | A configurable generic JSON encoder. This function applied to+-- 'defaultOptions' is used as the default for 'toEncoding' when the type+-- is an instance of 'Generic'.+genericToEncoding :: (Generic a, GToEncoding Zero (Rep a))+                  => Options -> a -> Encoding+genericToEncoding opts = gToEncoding opts NoToArgs . from++-- | A configurable generic JSON encoder. This function applied to+-- 'defaultOptions' is used as the default for 'liftToEncoding' when the type+-- is an instance of 'Generic1'.+genericLiftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f))+                      => Options -> (a -> Encoding) -> ([a] -> Encoding)+                      -> f a -> Encoding+genericLiftToEncoding opts te tel = gToEncoding opts (To1Args te tel) . from1++-------------------------------------------------------------------------------+-- Class+-------------------------------------------------------------------------------++-- | A type that can be converted to JSON.+--+-- An example type and instance:+--+-- @+-- \-- Allow ourselves to write 'Text' literals.+-- {-\# LANGUAGE OverloadedStrings #-}+--+-- data Coord = Coord { x :: Double, y :: Double }+--+-- instance ToJSON Coord where+--   toJSON (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]+--+--   toEncoding (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)+-- @+--+-- Instead of manually writing your 'ToJSON' instance, there are two options+-- to do it automatically:+--+-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an+-- instance at compile time. The generated instance is optimized for your type+-- so will probably be more efficient than the following two options:+--+-- * The compiler can provide a default generic implementation for+-- 'toJSON'.+--+-- To use the second, simply add a @deriving 'Generic'@ clause to your+-- datatype and declare a 'ToJSON' instance for your datatype without giving+-- definitions for 'toJSON' or 'toEncoding'.+--+-- For example, the previous example can be simplified to a more+-- minimal instance:+--+-- @+-- {-\# LANGUAGE DeriveGeneric \#-}+--+-- import "GHC.Generics"+--+-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'+--+-- instance ToJSON Coord where+--     toEncoding = 'genericToEncoding' 'defaultOptions'+-- @+--+-- Why do we provide an implementation for 'toEncoding' here?  The+-- 'toEncoding' function is a relatively new addition to this class.+-- To allow users of older versions of this library to upgrade without+-- having to edit all of their instances or encounter surprising+-- incompatibilities, the default implementation of 'toEncoding' uses+-- 'toJSON'.  This produces correct results, but since it performs an+-- intermediate conversion to a 'Value', it will be less efficient+-- than directly emitting an 'Encoding'.  Our one-liner definition of+-- 'toEncoding' above bypasses the intermediate 'Value'.+--+-- If @DefaultSignatures@ doesn't give exactly the results you want,+-- you can customize the generic encoding with only a tiny amount of+-- effort, using 'genericToJSON' and 'genericToEncoding' with your+-- preferred 'Options':+--+-- @+-- instance ToJSON Coord where+--     toJSON     = 'genericToJSON' 'defaultOptions'+--     toEncoding = 'genericToEncoding' 'defaultOptions'+-- @+class ToJSON a where+    -- | Convert a Haskell value to a JSON-friendly intermediate type.+    toJSON     :: a -> Value++    default toJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value+    toJSON = genericToJSON defaultOptions++    -- | Encode a Haskell value as JSON.+    --+    -- The default implementation of this method creates an+    -- intermediate 'Value' using 'toJSON'.  This provides+    -- source-level compatibility for people upgrading from older+    -- versions of this library, but obviously offers no performance+    -- advantage.+    --+    -- To benefit from direct encoding, you /must/ provide an+    -- implementation for this method.  The easiest way to do so is by+    -- having your types implement 'Generic' using the @DeriveGeneric@+    -- extension, and then have GHC generate a method body as follows.+    --+    -- @+    -- instance ToJSON Coord where+    --     toEncoding = 'genericToEncoding' 'defaultOptions'+    -- @++    toEncoding :: a -> Encoding+    toEncoding = E.value . toJSON+    {-# INLINE toEncoding #-}++    toJSONList :: [a] -> Value+    toJSONList = listValue toJSON+    {-# INLINE toJSONList #-}++    toEncodingList :: [a] -> Encoding+    toEncodingList = listEncoding toEncoding+    {-# INLINE toEncodingList #-}++-------------------------------------------------------------------------------+-- Object key-value pairs+-------------------------------------------------------------------------------++-- | A key-value pair for encoding a JSON object.+class KeyValue kv where+    (.=) :: ToJSON v => Text -> v -> kv+    infixr 8 .=++instance KeyValue Series where+    name .= value = E.pair name (toEncoding value)+    {-# INLINE (.=) #-}++instance KeyValue Pair where+    name .= value = (name, toJSON value)+    {-# INLINE (.=) #-}++-------------------------------------------------------------------------------+--  Classes and types for map keys+-------------------------------------------------------------------------------++-- | Typeclass for types that can be used as the key of a map-like container+--   (like 'Map' or 'HashMap'). For example, since 'Text' has a 'ToJSONKey'+--   instance and 'Char' has a 'ToJSON' instance, we can encode a value of+--   type 'Map' 'Text' 'Char':+--+--   >>> LBC8.putStrLn $ encode $ Map.fromList [("foo" :: Text, 'a')]+--   {"foo":"a"}+--+--   Since 'Int' also has a 'ToJSONKey' instance, we can similarly write:+--+--   >>> LBC8.putStrLn $ encode $ Map.fromList [(5 :: Int, 'a')]+--   {"5":"a"}+--+--   JSON documents only accept strings as object keys. For any type+--   from @base@ that has a natural textual representation, it can be+--   expected that its 'ToJSONKey' instance will choose that representation.+--+--   For data types that lack a natural textual representation, an alternative+--   is provided. The map-like container is represented as a JSON array+--   instead of a JSON object. Each value in the array is an array with+--   exactly two values. The first is the key and the second is the value.+--+--   For example, values of type '[Text]' cannot be encoded to a+--   string, so a 'Map' with keys of type '[Text]' is encoded as follows:+--+--   >>> LBC8.putStrLn $ encode $ Map.fromList [(["foo","bar","baz" :: Text], 'a')]+--   [[["foo","bar","baz"],"a"]]+--+--   The default implementation of 'ToJSONKey' chooses this method of+--   encoding a key, using the 'ToJSON' instance of the type.+--+--   To use your own data type as the key in a map, all that is needed+--   is to write a 'ToJSONKey' (and possibly a 'FromJSONKey') instance+--   for it. If the type cannot be trivially converted to and from 'Text',+--   it is recommended that 'ToJSONKeyValue' is used. Since the default+--   implementations of the typeclass methods can build this from a+--   'ToJSON' instance, there is nothing that needs to be written:+--+--   > data Foo = Foo { fooAge :: Int, fooName :: Text }+--   >   deriving (Eq,Ord,Generic)+--   > instance ToJSON Foo+--   > instance ToJSONKey Foo+--+--   That's it. We can now write:+--+--   >>> let m = Map.fromList [(Foo 4 "bar",'a'),(Foo 6 "arg",'b')]+--   >>> LBC8.putStrLn $ encode m+--   [[{"fooName":"bar","fooAge":4},"a"],[{"fooName":"arg","fooAge":6},"b"]]+--+--   The next case to consider is if we have a type that is a+--   newtype wrapper around 'Text'. The recommended approach is to use+--   generalized newtype deriving:+--+--   > newtype RecordId = RecordId { getRecordId :: Text}+--   >   deriving (Eq,Ord,ToJSONKey)+--+--   Then we may write:+--+--   >>> LBC8.putStrLn $ encode $ Map.fromList [(RecordId "abc",'a')]+--   {"abc":"a"}+--+--   Simple sum types are a final case worth considering. Suppose we have:+--+--   > data Color = Red | Green | Blue+--   >   deriving (Show,Read,Eq,Ord)+--+--   It is possible to get the 'ToJSONKey' instance for free as we did+--   with 'Foo'. However, in this case, we have a natural way to go to+--   and from 'Text' that does not require any escape sequences. So, in+--   this example, 'ToJSONKeyText' will be used instead of 'ToJSONKeyValue'.+--   The 'Show' instance can be used to help write 'ToJSONKey':+--+--   > instance ToJSONKey Color where+--   >   toJSONKey = ToJSONKeyText f g+--   >     where f = Text.pack . show+--   >           g = text . Text.pack . show+--   >           -- text function is from Data.Aeson.Encoding+--+--   The situation of needing to turning function @a -> Text@ into+--   a 'ToJSONKeyFunction' is common enough that a special combinator+--   is provided for it. The above instance can be rewritten as:+--+--   > instance ToJSONKey Color where+--   >   toJSONKey = toJSONKeyText (Text.pack . show)+--+--   The performance of the above instance can be improved by+--   not using 'String' as an intermediate step when converting to+--   'Text'. One option for improving performance would be to use+--   template haskell machinery from the @text-show@ package. However,+--   even with the approach, the 'Encoding' (a wrapper around a bytestring+--   builder) is generated by encoding the 'Text' to a 'ByteString',+--   an intermediate step that could be avoided. The fastest possible+--   implementation would be:+--+--   > -- Assuming that OverloadedStrings is enabled+--   > instance ToJSONKey Color where+--   >   toJSONKey = ToJSONKeyText f g+--   >     where f x = case x of {Red -> "Red";Green ->"Green";Blue -> "Blue"}+--   >           g x = case x of {Red -> text "Red";Green -> text "Green";Blue -> text "Blue"}+--   >           -- text function is from Data.Aeson.Encoding+--+--   This works because GHC can lift the encoded values out of the case+--   statements, which means that they are only evaluated once. This+--   approach should only be used when there is a serious need to+--   maximize performance.++class ToJSONKey a where+    -- | Strategy for rendering the key for a map-like container.+    toJSONKey :: ToJSONKeyFunction a+    default toJSONKey :: ToJSON a => ToJSONKeyFunction a+    toJSONKey = ToJSONKeyValue toJSON toEncoding++    -- | This is similar in spirit to the 'showsList' method of 'Show'.+    --   It makes it possible to give 'String' keys special treatment+    --   without using @OverlappingInstances@. End users should always+    --   be able to use the default implementation of this method.+    toJSONKeyList :: ToJSONKeyFunction [a]+    default toJSONKeyList :: ToJSON a => ToJSONKeyFunction [a]+    toJSONKeyList = ToJSONKeyValue toJSON toEncoding++data ToJSONKeyFunction a+    = ToJSONKeyText !(a -> Text) !(a -> Encoding' Text)+      -- ^ key is encoded to string, produces object+    | ToJSONKeyValue !(a -> Value) !(a -> Encoding)+      -- ^ key is encoded to value, produces array++-- | Helper for creating textual keys.+--+-- @+-- instance 'ToJSONKey' MyKey where+--     'toJSONKey' = 'toJSONKeyText' myKeyToText+--       where+--         myKeyToText = Text.pack . show -- or showt from text-show+-- @+toJSONKeyText :: (a -> Text) -> ToJSONKeyFunction a+toJSONKeyText f = ToJSONKeyText f (E.text . f)++-- | TODO: should this be exported?+toJSONKeyTextEnc :: (a -> Encoding' Text) -> ToJSONKeyFunction a+toJSONKeyTextEnc e = ToJSONKeyText tot e+ where+    -- TODO: dropAround is also used in stringEncoding, which is unfortunate atm+    tot = T.dropAround (== '"')+        . T.decodeLatin1+        . lazyToStrictByteString+        . E.encodingToLazyByteString+        . e++-- | Contravariant map, as 'ToJSONKeyFunction' is a contravariant functor.+contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b+contramapToJSONKeyFunction h x = case x of+    ToJSONKeyText  f g -> ToJSONKeyText (f . h) (g . h)+    ToJSONKeyValue f g -> ToJSONKeyValue (f . h) (g . h)++-------------------------------------------------------------------------------+-- Lifings of FromJSON and ToJSON to unary and binary type constructors+-------------------------------------------------------------------------------+++-- | Lifting of the 'ToJSON' class to unary type constructors.+--+-- Instead of manually writing your 'ToJSON1' instance, there are two options+-- to do it automatically:+--+-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an+-- instance at compile time. The generated instance is optimized for your type+-- so will probably be more efficient than the following two options:+--+-- * The compiler can provide a default generic implementation for+-- 'toJSON1'.+--+-- To use the second, simply add a @deriving 'Generic1'@ clause to your+-- datatype and declare a 'ToJSON1' instance for your datatype without giving+-- definitions for 'liftToJSON' or 'liftToEncoding'.+--+-- For example:+--+-- @+-- {-\# LANGUAGE DeriveGeneric \#-}+--+-- import "GHC.Generics"+--+-- data Pair = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'+--+-- instance ToJSON a => ToJSON1 (Pair a)+-- @+--+-- If @DefaultSignatures@ doesn't give exactly the results you want,+-- you can customize the generic encoding with only a tiny amount of+-- effort, using 'genericLiftToJSON' and 'genericLiftToEncoding' with+-- your preferred 'Options':+--+-- @+-- instance ToJSON a => ToJSON1 (Pair a) where+--     liftToJSON     = 'genericLiftToJSON' 'defaultOptions'+--     liftToEncoding = 'genericLiftToEncoding' 'defaultOptions'+-- @+class ToJSON1 f where+    liftToJSON :: (a -> Value) -> ([a] -> Value) -> f a -> Value++    default liftToJSON :: (Generic1 f, GToJSON One (Rep1 f))+                       => (a -> Value) -> ([a] -> Value) -> f a -> Value+    liftToJSON = genericLiftToJSON defaultOptions++    liftToJSONList :: (a -> Value) -> ([a] -> Value) -> [f a] -> Value+    liftToJSONList f g = listValue (liftToJSON f g)++    liftToEncoding :: (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding++    default liftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f))+                           => (a -> Encoding) -> ([a] -> Encoding)+                           -> f a -> Encoding+    liftToEncoding = genericLiftToEncoding defaultOptions++    liftToEncodingList :: (a -> Encoding) -> ([a] -> Encoding) -> [f a] -> Encoding+    liftToEncodingList f g = listEncoding (liftToEncoding f g)++-- | Lift the standard 'toJSON' function through the type constructor.+toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value+toJSON1 = liftToJSON toJSON toJSONList+{-# INLINE toJSON1 #-}++-- | Lift the standard 'toEncoding' function through the type constructor.+toEncoding1 :: (ToJSON1 f, ToJSON a) => f a -> Encoding+toEncoding1 = liftToEncoding toEncoding toEncodingList+{-# INLINE toEncoding1 #-}++-- | Lifting of the 'ToJSON' class to binary type constructors.+--+-- Instead of manually writing your 'ToJSON2' instance, "Data.Aeson.TH"+-- provides Template Haskell functions which will derive an instance at compile time.+--+-- The compiler cannot provide a default generic implementation for 'liftToJSON2',+-- unlike 'toJSON' and 'liftToJSON'.+class ToJSON2 f where+    liftToJSON2 :: (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> f a b -> Value+    liftToJSONList2 :: (a -> Value) -> ([a] -> Value) -> (b -> Value) -> ([b] -> Value) -> [f a b] -> Value+    liftToJSONList2 fa ga fb gb = listValue (liftToJSON2 fa ga fb gb)++    liftToEncoding2 :: (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> f a b -> Encoding+    liftToEncodingList2 :: (a -> Encoding) -> ([a] -> Encoding) -> (b -> Encoding) -> ([b] -> Encoding) -> [f a b] -> Encoding+    liftToEncodingList2 fa ga fb gb = listEncoding (liftToEncoding2 fa ga fb gb)++-- | Lift the standard 'toJSON' function through the type constructor.+toJSON2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Value+toJSON2 = liftToJSON2 toJSON toJSONList toJSON toJSONList+{-# INLINE toJSON2 #-}++-- | Lift the standard 'toEncoding' function through the type constructor.+toEncoding2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Encoding+toEncoding2 = liftToEncoding2 toEncoding toEncodingList toEncoding toEncodingList+{-# INLINE toEncoding2 #-}++-------------------------------------------------------------------------------+-- Encoding functions+-------------------------------------------------------------------------------++-- | Helper function to use with 'liftToEncoding'.+-- Useful when writing own 'ToJSON1' instances.+--+-- @+-- newtype F a = F [a]+--+-- -- This instance encodes String as an array of chars+-- instance 'ToJSON1' F where+--     'liftToJSON'     tj _ (F xs) = 'liftToJSON'     tj ('listValue'    tj) xs+--     'liftToEncoding' te _ (F xs) = 'liftToEncoding' te ('listEncoding' te) xs+--+-- instance 'Data.Aeson.FromJSON.FromJSON1' F where+--     'Data.Aeson.FromJSON.liftParseJSON' p _ v = F \<$\> 'Data.Aeson.FromJSON.liftParseJSON' p ('Data.Aeson.FromJSON.listParser' p) v+-- @+listEncoding :: (a -> Encoding) -> [a] -> Encoding+listEncoding = E.list+{-# INLINE listEncoding #-}++-- | Helper function to use with 'liftToJSON', see 'listEncoding'.+listValue :: (a -> Value) -> [a] -> Value+listValue f = Array . V.fromList . map f+{-# INLINE listValue #-}++-------------------------------------------------------------------------------+-- [] instances+-------------------------------------------------------------------------------++-- These are needed for key-class default definitions++instance ToJSON1 [] where+    liftToJSON _ to' = to'+    {-# INLINE liftToJSON #-}++    liftToEncoding _ to' = to'+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON [a] where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- Generic toJSON / toEncoding+-------------------------------------------------------------------------------++--------------------------------------------------------------------------------+-- Generic toJSON++instance OVERLAPPABLE_ (GToJSON arity a) => GToJSON arity (M1 i c a) where+    -- Meta-information, which is not handled elsewhere, is ignored:+    gToJSON opts targs = gToJSON opts targs . unM1++instance (ToJSON a) => GToJSON arity (K1 i a) where+    -- Constant values are encoded using their ToJSON instance:+    gToJSON _opts _ = toJSON . unK1++instance GToJSON One Par1 where+    -- Direct occurrences of the last type parameter are encoded with the+    -- function passed in as an argument:+    gToJSON _opts (To1Args tj _) = tj . unPar1++instance (ToJSON1 f) => GToJSON One (Rec1 f) where+    -- Recursive occurrences of the last type parameter are encoded using their+    -- ToJSON1 instance:+    gToJSON _opts (To1Args tj tjl) = liftToJSON tj tjl . unRec1++instance GToJSON arity U1 where+    -- Empty constructors are encoded to an empty array:+    gToJSON _opts _ _ = emptyArray++instance (ConsToJSON arity a) => GToJSON arity (C1 c a) where+    -- Constructors need to be encoded differently depending on whether they're+    -- a record or not. This distinction is made by 'consToJSON':+    gToJSON opts targs = consToJSON opts targs . unM1++instance ( WriteProduct arity a, WriteProduct arity b+         , ProductSize        a, ProductSize        b+         ) => GToJSON arity (a :*: b) where+    -- Products are encoded to an array. Here we allocate a mutable vector of+    -- the same size as the product and write the product's elements to it using+    -- 'writeProduct':+    gToJSON opts targs p =+        Array $ V.create $ do+          mv <- VM.unsafeNew lenProduct+          writeProduct opts targs mv 0 lenProduct p+          return mv+        where+          lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)+                       productSize++instance ( AllNullary       (a :+: b) allNullary+         , SumToJSON  arity (a :+: b) allNullary+         ) => GToJSON arity (a :+: b) where+    -- If all constructors of a sum datatype are nullary and the+    -- 'allNullaryToStringTag' option is set they are encoded to+    -- strings.  This distinction is made by 'sumToJSON':+    gToJSON opts targs = (unTagged :: Tagged allNullary Value -> Value)+                       . sumToJSON opts targs++instance (ToJSON1 f, GToJSON One g) => GToJSON One (f :.: g) where+    -- If an occurrence of the last type parameter is nested inside two+    -- composed types, it is encoded by using the outermost type's ToJSON1+    -- instance to generically encode the innermost type:+    gToJSON opts targs =+      let gtj = gToJSON opts targs in+      liftToJSON gtj (listValue gtj) . unComp1++--------------------------------------------------------------------------------+-- Generic toEncoding++instance OVERLAPPABLE_ (GToEncoding arity a) => GToEncoding arity (M1 i c a) where+    -- Meta-information, which is not handled elsewhere, is ignored:+    gToEncoding opts targs = gToEncoding opts targs . unM1++instance (ToJSON a) => GToEncoding arity (K1 i a) where+    -- Constant values are encoded using their ToJSON instance:+    gToEncoding _opts _ = toEncoding . unK1++instance GToEncoding One Par1 where+    -- Direct occurrences of the last type parameter are encoded with the+    -- function passed in as an argument:+    gToEncoding _opts (To1Args te _) = te . unPar1++instance (ToJSON1 f) => GToEncoding One (Rec1 f) where+    -- Recursive occurrences of the last type parameter are encoded using their+    -- ToEncoding1 instance:+    gToEncoding _opts (To1Args te tel) = liftToEncoding te tel . unRec1++instance GToEncoding arity U1 where+    -- Empty constructors are encoded to an empty array:+    gToEncoding _opts _ _ = E.emptyArray_++instance (ConsToEncoding arity a) => GToEncoding arity (C1 c a) where+    -- Constructors need to be encoded differently depending on whether they're+    -- a record or not. This distinction is made by 'consToEncoding':+    gToEncoding opts targs = consToEncoding opts targs . unM1++instance ( EncodeProduct  arity a+         , EncodeProduct  arity b+         ) => GToEncoding arity (a :*: b) where+    -- Products are encoded to an array. Here we allocate a mutable vector of+    -- the same size as the product and write the product's elements to it using+    -- 'encodeProduct':+    gToEncoding opts targs p = E.list E.retagEncoding [encodeProduct opts targs p]++instance ( AllNullary           (a :+: b) allNullary+         , SumToEncoding  arity (a :+: b) allNullary+         ) => GToEncoding arity (a :+: b) where+    -- If all constructors of a sum datatype are nullary and the+    -- 'allNullaryToStringTag' option is set they are encoded to+    -- strings.  This distinction is made by 'sumToEncoding':+    gToEncoding opts targs+        = (unTagged :: Tagged allNullary Encoding -> Encoding)+        . sumToEncoding opts targs++instance (ToJSON1 f, GToEncoding One g) => GToEncoding One (f :.: g) where+    -- If an occurrence of the last type parameter is nested inside two+    -- composed types, it is encoded by using the outermost type's ToJSON1+    -- instance to generically encode the innermost type:+    gToEncoding opts targs =+      let gte = gToEncoding opts targs in+      liftToEncoding gte (listEncoding gte) . unComp1++--------------------------------------------------------------------------------++class SumToJSON arity f allNullary where+    sumToJSON :: Options -> ToArgs Value arity a+              -> f a -> Tagged allNullary Value++instance ( GetConName                     f+         , TaggedObjectPairs        arity f+         , ObjectWithSingleFieldObj arity f+         , TwoElemArrayObj          arity f+         , UntaggedValueObj         arity f+         ) => SumToJSON arity f True where+    sumToJSON opts targs+        | allNullaryToStringTag opts = Tagged . String . pack+                                     . constructorTagModifier opts . getConName+        | otherwise = Tagged . nonAllNullarySumToJSON opts targs++instance ( TwoElemArrayObj          arity f+         , TaggedObjectPairs        arity f+         , ObjectWithSingleFieldObj arity f+         , UntaggedValueObj         arity f+         ) => SumToJSON arity f False where+    sumToJSON opts targs = Tagged . nonAllNullarySumToJSON opts targs++nonAllNullarySumToJSON :: ( TwoElemArrayObj          arity f+                          , TaggedObjectPairs        arity f+                          , ObjectWithSingleFieldObj arity f+                          , UntaggedValueObj         arity f+                          ) => Options -> ToArgs Value arity a+                            -> f a -> Value+nonAllNullarySumToJSON opts targs =+    case sumEncoding opts of+      TaggedObject{..}      ->+        object . taggedObjectPairs opts targs tagFieldName contentsFieldName+      ObjectWithSingleField -> Object . objectWithSingleFieldObj opts targs+      TwoElemArray          -> Array  . twoElemArrayObj opts targs+      UntaggedValue         -> untaggedValueObj opts targs++--------------------------------------------------------------------------------++class SumToEncoding arity f allNullary where+    sumToEncoding :: Options -> ToArgs Encoding arity a+                  -> f a -> Tagged allNullary Encoding++instance ( GetConName                     f+         , TaggedObjectEnc          arity f+         , ObjectWithSingleFieldEnc arity f+         , TwoElemArrayEnc          arity f+         , UntaggedValueEnc         arity f+         ) => SumToEncoding arity f True where+    sumToEncoding opts targs+        | allNullaryToStringTag opts = Tagged . toEncoding .+                                       constructorTagModifier opts . getConName+        | otherwise = Tagged . nonAllNullarySumToEncoding opts targs++instance ( TwoElemArrayEnc          arity f+         , TaggedObjectEnc          arity f+         , ObjectWithSingleFieldEnc arity f+         , UntaggedValueEnc         arity f+         ) => SumToEncoding arity f False where+    sumToEncoding opts targs = Tagged . nonAllNullarySumToEncoding opts targs++nonAllNullarySumToEncoding :: ( TwoElemArrayEnc          arity f+                              , TaggedObjectEnc          arity f+                              , ObjectWithSingleFieldEnc arity f+                              , UntaggedValueEnc         arity f+                              ) => Options -> ToArgs Encoding arity a+                                -> f a -> Encoding+nonAllNullarySumToEncoding opts targs =+    case sumEncoding opts of+      TaggedObject{..}      ->+        taggedObjectEnc opts targs tagFieldName contentsFieldName+      ObjectWithSingleField -> objectWithSingleFieldEnc opts targs+      TwoElemArray          -> twoElemArrayEnc opts targs+      UntaggedValue         -> untaggedValueEnc opts targs++--------------------------------------------------------------------------------++class TaggedObjectPairs arity f where+    taggedObjectPairs :: Options -> ToArgs Value arity a+                      -> String -> String+                      -> f a -> [Pair]++instance ( TaggedObjectPairs arity a+         , TaggedObjectPairs arity b+         ) => TaggedObjectPairs arity (a :+: b) where+    taggedObjectPairs opts targs tagFieldName contentsFieldName (L1 x) =+        taggedObjectPairs opts targs tagFieldName contentsFieldName x+    taggedObjectPairs opts targs tagFieldName contentsFieldName (R1 x) =+        taggedObjectPairs opts targs tagFieldName contentsFieldName x++instance ( IsRecord                 a isRecord+         , TaggedObjectPairs' arity a isRecord+         , Constructor c+         ) => TaggedObjectPairs arity (C1 c a) where+    taggedObjectPairs opts targs tagFieldName contentsFieldName =+        (pack tagFieldName .= constructorTagModifier opts+                                 (conName (undefined :: t c a p)) :) .+        (unTagged :: Tagged isRecord [Pair] -> [Pair]) .+          taggedObjectPairs' opts targs contentsFieldName . unM1++class TaggedObjectPairs' arity f isRecord where+    taggedObjectPairs' :: Options -> ToArgs Value arity a+                       -> String -> f a -> Tagged isRecord [Pair]++instance OVERLAPPING_ TaggedObjectPairs' arity U1 False where+    taggedObjectPairs' _ _ _ _ = Tagged []++instance (RecordToPairs arity f) => TaggedObjectPairs' arity f True where+    taggedObjectPairs' opts targs _ =+      Tagged . toList . recordToPairs opts targs++instance (GToJSON arity f) => TaggedObjectPairs' arity f False where+    taggedObjectPairs' opts targs contentsFieldName =+        Tagged . (:[]) . (pack contentsFieldName .=) . gToJSON opts targs++--------------------------------------------------------------------------------++class TaggedObjectEnc arity f where+    taggedObjectEnc :: Options -> ToArgs Encoding arity a+                    -> String -> String+                    -> f a -> Encoding++instance ( TaggedObjectEnc    arity a+         , TaggedObjectEnc    arity b+         ) => TaggedObjectEnc arity (a :+: b) where+    taggedObjectEnc opts targs tagFieldName contentsFieldName (L1 x) =+        taggedObjectEnc opts targs tagFieldName contentsFieldName x+    taggedObjectEnc opts targs tagFieldName contentsFieldName (R1 x) =+        taggedObjectEnc opts targs tagFieldName contentsFieldName x++instance ( IsRecord               a isRecord+         , TaggedObjectEnc' arity a isRecord+         , Constructor c+         ) => TaggedObjectEnc arity (C1 c a) where+    taggedObjectEnc opts targs tagFieldName contentsFieldName v = E.pairs (E.pair key val)+      where+        key :: Text+        key = pack tagFieldName+        val = toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))+           >< ((unTagged :: Tagged isRecord Encoding -> Encoding) . taggedObjectEnc' opts targs contentsFieldName . unM1 $ v)++class TaggedObjectEnc' arity f isRecord where+    taggedObjectEnc' :: Options -> ToArgs Encoding arity a+                     -> String -> f a -> Tagged isRecord Encoding++instance OVERLAPPING_ TaggedObjectEnc' arity U1 False where+    taggedObjectEnc' _ _ _ _ = Tagged E.empty++instance (RecordToEncoding arity f) => TaggedObjectEnc' arity f True where+    taggedObjectEnc' opts targs _ = Tagged . (E.comma ><) . fst+                                           . recordToEncoding opts targs++instance (GToEncoding arity f) => TaggedObjectEnc' arity f False where+    taggedObjectEnc' opts targs contentsFieldName =+        Tagged . (\z -> E.comma >< toEncoding contentsFieldName >< E.colon >< z) .+        gToEncoding opts targs++--------------------------------------------------------------------------------++-- | Get the name of the constructor of a sum datatype.+class GetConName f where+    getConName :: f a -> String++instance (GetConName a, GetConName b) => GetConName (a :+: b) where+    getConName (L1 x) = getConName x+    getConName (R1 x) = getConName x++instance (Constructor c) => GetConName (C1 c a) where+    getConName = conName++--------------------------------------------------------------------------------++class TwoElemArrayObj arity f where+    twoElemArrayObj :: Options -> ToArgs Value arity a+                    -> f a -> V.Vector Value++instance ( TwoElemArrayObj arity a+         , TwoElemArrayObj arity b+         ) => TwoElemArrayObj arity (a :+: b) where+    twoElemArrayObj opts targs (L1 x) = twoElemArrayObj opts targs x+    twoElemArrayObj opts targs (R1 x) = twoElemArrayObj opts targs x++instance ( GToJSON    arity a+         , ConsToJSON arity a+         , Constructor c+         ) => TwoElemArrayObj arity (C1 c a) where+    twoElemArrayObj opts targs x = V.create $ do+      mv <- VM.unsafeNew 2+      VM.unsafeWrite mv 0 $ String $ pack $ constructorTagModifier opts+                                   $ conName (undefined :: t c a p)+      VM.unsafeWrite mv 1 $ gToJSON opts targs x+      return mv++--------------------------------------------------------------------------------++class TwoElemArrayEnc arity f where+    twoElemArrayEnc :: Options -> ToArgs Encoding arity a+                    -> f a -> Encoding++instance ( TwoElemArrayEnc    arity a+         , TwoElemArrayEnc    arity b+         ) => TwoElemArrayEnc arity (a :+: b) where+    twoElemArrayEnc opts targs (L1 x) = twoElemArrayEnc opts targs x+    twoElemArrayEnc opts targs (R1 x) = twoElemArrayEnc opts targs x++instance ( GToEncoding    arity a+         , ConsToEncoding arity a+         , Constructor c+         ) => TwoElemArrayEnc arity (C1 c a) where+    twoElemArrayEnc opts targs x = E.list id+      [ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))+      , gToEncoding opts targs x+      ]++--------------------------------------------------------------------------------++class ConsToJSON arity f where+    consToJSON     :: Options -> ToArgs Value arity a+                   -> f a -> Value++class ConsToJSON' arity f isRecord where+    consToJSON'     :: Options -> ToArgs Value arity a+                    -> Bool -- ^ Are we a record with one field?+                    -> f a -> Tagged isRecord Value++instance ( IsRecord          f isRecord+         , ConsToJSON' arity f isRecord+         ) => ConsToJSON arity f where+    consToJSON opts targs =+        (unTagged :: Tagged isRecord Value -> Value)+      . consToJSON' opts targs (isUnary (undefined :: f a))++instance (RecordToPairs arity f) => ConsToJSON' arity f True where+    consToJSON' opts targs isUn f = let+      vals = toList $ recordToPairs opts targs f+      in case (unwrapUnaryRecords opts,isUn,vals) of+        (True,True,[(_,val)]) -> Tagged val+        _ -> Tagged $ object vals++instance GToJSON arity f => ConsToJSON' arity f False where+    consToJSON' opts targs _ = Tagged . gToJSON opts targs++--------------------------------------------------------------------------------++class ConsToEncoding arity f where+    consToEncoding :: Options -> ToArgs Encoding arity a+                   -> f a -> Encoding++class ConsToEncoding' arity f isRecord where+    consToEncoding' :: Options -> ToArgs Encoding arity a+                    -> Bool -- ^ Are we a record with one field?+                    -> f a -> Tagged isRecord Encoding++instance ( IsRecord                f isRecord+         , ConsToEncoding'   arity f isRecord+         ) => ConsToEncoding arity f where+    consToEncoding opts targs =+        (unTagged :: Tagged isRecord Encoding -> Encoding)+      . consToEncoding' opts targs (isUnary (undefined :: f a))++instance (RecordToEncoding arity f) => ConsToEncoding' arity f True where+    consToEncoding' opts targs isUn x =+      let (enc, mbVal) = recordToEncoding opts targs x+      in case (unwrapUnaryRecords opts, isUn, mbVal) of+           (True, True, Just val) -> Tagged val+           _ -> Tagged $ E.wrapObject enc++instance GToEncoding arity f => ConsToEncoding' arity f False where+    consToEncoding' opts targs _ = Tagged . gToEncoding opts targs++--------------------------------------------------------------------------------++class RecordToPairs arity f where+    recordToPairs    :: Options -> ToArgs Value arity a+                     -> f a -> DList Pair++instance ( RecordToPairs arity a+         , RecordToPairs arity b+         ) => RecordToPairs arity (a :*: b) where+    recordToPairs opts targs (a :*: b) = recordToPairs opts targs a <>+                                         recordToPairs opts targs b++instance (Selector s, GToJSON arity a) => RecordToPairs arity (S1 s a) where+    recordToPairs = fieldToPair++instance OVERLAPPING_ (Selector s, ToJSON a) =>+  RecordToPairs arity (S1 s (K1 i (Maybe a))) where+    recordToPairs opts _ (M1 k1) | omitNothingFields opts+                                 , K1 Nothing <- k1 = DList.empty+    recordToPairs opts targs m1 = fieldToPair opts targs m1++fieldToPair :: (Selector s, GToJSON arity a)+            => Options -> ToArgs Value arity p+            -> S1 s a p -> DList Pair+fieldToPair opts targs m1 = pure ( pack $ fieldLabelModifier opts $ selName m1+                                 , gToJSON opts targs (unM1 m1)+                                 )++--------------------------------------------------------------------------------++class RecordToEncoding arity f where+    -- 1st element: whole thing+    -- 2nd element: in case the record has only 1 field, just the value+    --              of the field (without the key); 'Nothing' otherwise+    recordToEncoding :: Options -> ToArgs Encoding arity a+                     -> f a -> (Encoding, Maybe Encoding)++instance ( RecordToEncoding    arity a+         , RecordToEncoding    arity b+         ) => RecordToEncoding arity (a :*: b) where+    recordToEncoding opts targs (a :*: b) | omitNothingFields opts =+      (E.econcat $ intersperse E.comma $+        filter (not . E.nullEncoding)+        [ fst (recordToEncoding opts targs a)+        , fst (recordToEncoding opts targs b) ]+      , Nothing)+    recordToEncoding opts targs (a :*: b) =+      (fst (recordToEncoding opts targs a) >< E.comma ><+       fst (recordToEncoding opts targs b),+       Nothing)+++instance (Selector s, GToEncoding arity a) => RecordToEncoding arity (S1 s a) where+    recordToEncoding = fieldToEncoding++instance OVERLAPPING_ (Selector s, ToJSON a) =>+  RecordToEncoding arity (S1 s (K1 i (Maybe a))) where+    recordToEncoding opts _ (M1 k1) | omitNothingFields opts+                                    , K1 Nothing <- k1 = (E.empty, Nothing)+    recordToEncoding opts targs m1 = fieldToEncoding opts targs m1++fieldToEncoding :: (Selector s, GToEncoding arity a)+                => Options -> ToArgs Encoding arity p+                -> S1 s a p -> (Encoding, Maybe Encoding)+fieldToEncoding opts targs m1 =+  let keyBuilder = toEncoding (fieldLabelModifier opts $ selName m1)+      valueBuilder = gToEncoding opts targs (unM1 m1)+  in  (keyBuilder >< E.colon >< valueBuilder, Just valueBuilder)++--------------------------------------------------------------------------------++class WriteProduct arity f where+    writeProduct :: Options+                 -> ToArgs Value arity a+                 -> VM.MVector s Value+                 -> Int -- ^ index+                 -> Int -- ^ length+                 -> f a+                 -> ST s ()++instance ( WriteProduct arity a+         , WriteProduct arity b+         ) => WriteProduct arity (a :*: b) where+    writeProduct opts targs mv ix len (a :*: b) = do+      writeProduct opts targs mv ix  lenL a+      writeProduct opts targs mv ixR lenR b+        where+          lenL = len `unsafeShiftR` 1+          lenR = len - lenL+          ixR  = ix  + lenL++instance OVERLAPPABLE_ (GToJSON arity a) => WriteProduct arity a where+    writeProduct opts targs mv ix _ =+      VM.unsafeWrite mv ix . gToJSON opts targs++--------------------------------------------------------------------------------++class EncodeProduct arity f where+    encodeProduct :: Options -> ToArgs Encoding arity a+                  -> f a -> Encoding' E.InArray++instance ( EncodeProduct    arity a+         , EncodeProduct    arity b+         ) => EncodeProduct arity (a :*: b) where+    encodeProduct opts targs (a :*: b) | omitNothingFields opts =+        E.econcat $ intersperse E.comma $+        filter (not . E.nullEncoding)+        [encodeProduct opts targs a, encodeProduct opts targs b]+    encodeProduct opts targs (a :*: b) =+      encodeProduct opts targs a >*<+      encodeProduct opts targs b++instance OVERLAPPABLE_ (GToEncoding arity a) => EncodeProduct arity a where+    encodeProduct opts targs a = E.retagEncoding $ gToEncoding opts targs a++--------------------------------------------------------------------------------++class ObjectWithSingleFieldObj arity f where+    objectWithSingleFieldObj :: Options -> ToArgs Value arity a+                             -> f a -> Object++instance ( ObjectWithSingleFieldObj arity a+         , ObjectWithSingleFieldObj arity b+         ) => ObjectWithSingleFieldObj arity (a :+: b) where+    objectWithSingleFieldObj opts targs (L1 x) =+      objectWithSingleFieldObj opts targs x+    objectWithSingleFieldObj opts targs (R1 x) =+      objectWithSingleFieldObj opts targs x++instance ( GToJSON    arity a+         , ConsToJSON arity a+         , Constructor c+         ) => ObjectWithSingleFieldObj arity (C1 c a) where+    objectWithSingleFieldObj opts targs = H.singleton typ . gToJSON opts targs+        where+          typ = pack $ constructorTagModifier opts $+                         conName (undefined :: t c a p)++--------------------------------------------------------------------------------++class ObjectWithSingleFieldEnc arity f where+    objectWithSingleFieldEnc :: Options -> ToArgs Encoding arity a+                             -> f a -> Encoding++instance ( ObjectWithSingleFieldEnc    arity a+         , ObjectWithSingleFieldEnc    arity b+         ) => ObjectWithSingleFieldEnc arity (a :+: b) where+    objectWithSingleFieldEnc opts targs (L1 x) =+      objectWithSingleFieldEnc opts targs x+    objectWithSingleFieldEnc opts targs (R1 x) =+      objectWithSingleFieldEnc opts targs x++instance ( GToEncoding    arity a+         , ConsToEncoding arity a+         , Constructor c+         ) => ObjectWithSingleFieldEnc arity (C1 c a) where+    objectWithSingleFieldEnc opts targs v = E.pairs (E.pair key val)+      where+        key :: Text+        key = pack (constructorTagModifier opts (conName (undefined :: t c a p)))+        val :: Encoding' Value+        val = gToEncoding opts targs v++--------------------------------------------------------------------------------++class UntaggedValueObj arity f where+    untaggedValueObj :: Options -> ToArgs Value arity a+                     -> f a -> Value++instance+    ( UntaggedValueObj    arity a+    , UntaggedValueObj    arity b+    ) => UntaggedValueObj arity (a :+: b)+  where+    untaggedValueObj opts targs (L1 x) = untaggedValueObj opts targs x+    untaggedValueObj opts targs (R1 x) = untaggedValueObj opts targs x++instance OVERLAPPABLE_+    ( GToJSON             arity a+    , ConsToJSON          arity a+    ) => UntaggedValueObj arity (C1 c a) where+    untaggedValueObj = gToJSON++instance OVERLAPPING_+    ( Constructor c )+    => UntaggedValueObj arity (C1 c U1)+  where+    untaggedValueObj opts _ _ = toJSON $+        constructorTagModifier opts $ conName (undefined :: t c U1 p)++--------------------------------------------------------------------------------++class UntaggedValueEnc arity f where+    untaggedValueEnc :: Options -> ToArgs Encoding arity a+                     -> f a -> Encoding+instance+    ( UntaggedValueEnc    arity a+    , UntaggedValueEnc    arity b+    ) => UntaggedValueEnc arity (a :+: b)+  where+    untaggedValueEnc opts targs (L1 x) = untaggedValueEnc opts targs x+    untaggedValueEnc opts targs (R1 x) = untaggedValueEnc opts targs x++instance OVERLAPPABLE_+    ( GToEncoding         arity a+    , ConsToEncoding      arity a+    ) => UntaggedValueEnc arity (C1 c a)+  where+    untaggedValueEnc = gToEncoding++instance OVERLAPPING_+    ( Constructor c )+    => UntaggedValueEnc arity (C1 c U1)+  where+    untaggedValueEnc opts _ _ = toEncoding $+        constructorTagModifier opts $ conName (undefined :: t c U1 p)++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++-------------------------------------------------------------------------------+-- base+-------------------------------------------------------------------------------++instance ToJSON2 Const where+    liftToJSON2 t _ _ _ (Const x) = t x+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 t _ _ _ (Const x) = t x+    {-# INLINE liftToEncoding2 #-}++instance ToJSON a => ToJSON1 (Const a) where+    liftToJSON _ _ (Const x) = toJSON x+    {-# INLINE liftToJSON #-}++    liftToEncoding _ _ (Const x) = toEncoding x+    {-# INLINE liftToEncoding #-}++instance ToJSON a => ToJSON (Const a b) where+    toJSON (Const x) = toJSON x+    {-# INLINE toJSON #-}++    toEncoding (Const x) = toEncoding x+    {-# INLINE toEncoding #-}+++instance ToJSON1 Maybe where+    liftToJSON t _ (Just a) = t a+    liftToJSON _  _ Nothing  = Null+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ (Just a) = t a+    liftToEncoding _  _ Nothing  = E.null_+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (Maybe a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON2 Either where+    liftToJSON2  toA _ _toB _ (Left a)  = Object $ H.singleton "Left"  (toA a)+    liftToJSON2 _toA _  toB _ (Right b) = Object $ H.singleton "Right" (toB b)+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2  toA _ _toB _ (Left a) = E.pairs $ E.pair "Left" $ toA a++    liftToEncoding2 _toA _ toB _ (Right b) = E.pairs $ E.pair "Right" $ toB b+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a) => ToJSON1 (Either a) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}++    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}++    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}+++instance ToJSON Bool where+    toJSON = Bool+    {-# INLINE toJSON #-}++    toEncoding = E.bool+    {-# INLINE toEncoding #-}++instance ToJSONKey Bool where+    toJSONKey = toJSONKeyText $ \x -> if x then "true" else "false"+++instance ToJSON Ordering where+  toJSON     = toJSON     . orderingToText+  toEncoding = toEncoding . orderingToText++orderingToText :: Ordering -> T.Text+orderingToText o = case o of+                     LT -> "LT"+                     EQ -> "EQ"+                     GT -> "GT"++instance ToJSON () where+    toJSON _ = emptyArray+    {-# INLINE toJSON #-}++    toEncoding _ = emptyArray_+    {-# INLINE toEncoding #-}+++instance ToJSON Char where+    toJSON = String . T.singleton+    {-# INLINE toJSON #-}++    toJSONList = String . T.pack+    {-# INLINE toJSONList #-}++    toEncoding = E.string . (:[])+    {-# INLINE toEncoding #-}++    toEncodingList = E.string+    {-# INLINE toEncodingList #-}+++instance ToJSON Double where+    toJSON = realFloatToJSON+    {-# INLINE toJSON #-}++    toEncoding = E.double+    {-# INLINE toEncoding #-}++instance ToJSONKey Double where+    toJSONKey = toJSONKeyTextEnc E.doubleText+    {-# INLINE toJSONKey #-}+++instance ToJSON Number where+    toJSON (D d) = toJSON d+    toJSON (I i) = toJSON i+    {-# INLINE toJSON #-}++    toEncoding (D d) = toEncoding d+    toEncoding (I i) = toEncoding i+    {-# INLINE toEncoding #-}+++instance ToJSON Float where+    toJSON = realFloatToJSON+    {-# INLINE toJSON #-}++    toEncoding = E.float+    {-# INLINE toEncoding #-}++instance ToJSONKey Float where+    toJSONKey = toJSONKeyTextEnc E.floatText+    {-# INLINE toJSONKey #-}+++instance (ToJSON a, Integral a) => ToJSON (Ratio a) where+    toJSON r = object [ "numerator"   .= numerator   r+                      , "denominator" .= denominator r+                      ]+    {-# INLINE toJSON #-}++    toEncoding r = E.pairs $+        "numerator" .= numerator r <>+        "denominator" .= denominator r+    {-# INLINE toEncoding #-}+++instance HasResolution a => ToJSON (Fixed a) where+    toJSON = Number . realToFrac+    {-# INLINE toJSON #-}++    toEncoding = E.scientific . realToFrac+    {-# INLINE toEncoding #-}++instance HasResolution a => ToJSONKey (Fixed a) where+    toJSONKey = toJSONKeyTextEnc (E.scientificText . realToFrac)+    {-# INLINE toJSONKey #-}+++instance ToJSON Int where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.int+    {-# INLINE toEncoding #-}++instance ToJSONKey Int where+    toJSONKey = toJSONKeyTextEnc E.intText+    {-# INLINE toJSONKey #-}+++instance ToJSON Integer where+    toJSON = Number . fromInteger+    {-# INLINE toJSON #-}++    toEncoding = E.integer+    {-# INLINE toEncoding #-}++instance ToJSONKey Integer where+    toJSONKey = toJSONKeyTextEnc E.integerText+    {-# INLINE toJSONKey #-}+++instance ToJSON Natural where+    toJSON = toJSON . toInteger+    {-# INLINE toJSON #-}++    toEncoding = toEncoding . toInteger+    {-# INLINE toEncoding #-}++instance ToJSONKey Natural where+    toJSONKey = toJSONKeyTextEnc (E.integerText . toInteger)+    {-# INLINE toJSONKey #-}+++instance ToJSON Int8 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.int8+    {-# INLINE toEncoding #-}++instance ToJSONKey Int8 where+    toJSONKey = toJSONKeyTextEnc E.int8Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Int16 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.int16+    {-# INLINE toEncoding #-}++instance ToJSONKey Int16 where+    toJSONKey = toJSONKeyTextEnc E.int16Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Int32 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.int32+    {-# INLINE toEncoding #-}++instance ToJSONKey Int32 where+    toJSONKey = toJSONKeyTextEnc E.int32Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Int64 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.int64+    {-# INLINE toEncoding #-}++instance ToJSONKey Int64 where+    toJSONKey = toJSONKeyTextEnc E.int64Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Word where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.word+    {-# INLINE toEncoding #-}++instance ToJSONKey Word where+    toJSONKey = toJSONKeyTextEnc E.wordText+    {-# INLINE toJSONKey #-}+++instance ToJSON Word8 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.word8+    {-# INLINE toEncoding #-}++instance ToJSONKey Word8 where+    toJSONKey = toJSONKeyTextEnc E.word8Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Word16 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.word16+    {-# INLINE toEncoding #-}++instance ToJSONKey Word16 where+    toJSONKey = toJSONKeyTextEnc E.word16Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Word32 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.word32+    {-# INLINE toEncoding #-}++instance ToJSONKey Word32 where+    toJSONKey = toJSONKeyTextEnc E.word32Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Word64 where+    toJSON = Number . fromIntegral+    {-# INLINE toJSON #-}++    toEncoding = E.word64+    {-# INLINE toEncoding #-}++instance ToJSONKey Word64 where+    toJSONKey = toJSONKeyTextEnc E.word64Text+    {-# INLINE toJSONKey #-}+++instance ToJSON Text where+    toJSON = String+    {-# INLINE toJSON #-}++    toEncoding = E.text+    {-# INLINE toEncoding #-}++instance ToJSONKey Text where+    toJSONKey = toJSONKeyText id+    {-# INLINE toJSONKey #-}+++instance ToJSON LT.Text where+    toJSON = String . LT.toStrict+    {-# INLINE toJSON #-}++    toEncoding = E.lazyText+    {-# INLINE toEncoding #-}++instance ToJSONKey LT.Text where+    toJSONKey = toJSONKeyText LT.toStrict+++instance ToJSON Version where+    toJSON = toJSON . showVersion+    {-# INLINE toJSON #-}++    toEncoding = toEncoding . showVersion+    {-# INLINE toEncoding #-}++instance ToJSONKey Version where+    toJSONKey = toJSONKeyText (T.pack . showVersion)++-------------------------------------------------------------------------------+-- semigroups NonEmpty+-------------------------------------------------------------------------------++instance ToJSON1 NonEmpty where+    liftToJSON t _ = listValue t . NE.toList+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = listEncoding t . NE.toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (NonEmpty a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- scientific+-------------------------------------------------------------------------------++instance ToJSON Scientific where+    toJSON = Number+    {-# INLINE toJSON #-}++    toEncoding = E.scientific+    {-# INLINE toEncoding #-}++instance ToJSONKey Scientific where+    toJSONKey = toJSONKeyTextEnc E.scientificText++-------------------------------------------------------------------------------+-- DList+-------------------------------------------------------------------------------++instance ToJSON1 DList.DList where+    liftToJSON t _ = listValue t . toList+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = listEncoding t . toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (DList.DList a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- transformers - Functors+-------------------------------------------------------------------------------++instance ToJSON1 Identity where+    liftToJSON t _ (Identity a) = t a+    {-# INLINE liftToJSON #-}++    liftToJSONList _ tl xs = tl (map runIdentity xs)+    {-# INLINE liftToJSONList #-}++    liftToEncoding t _ (Identity a) = t a+    {-# INLINE liftToEncoding #-}++    liftToEncodingList _ tl xs = tl (map runIdentity xs)+    {-# INLINE liftToEncodingList #-}++instance (ToJSON a) => ToJSON (Identity a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toJSONList = liftToJSONList toJSON toJSONList+    {-# INLINE toJSONList #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++    toEncodingList = liftToEncodingList toEncoding toEncodingList+    {-# INLINE toEncodingList #-}++instance (ToJSONKey a, ToJSON a) => ToJSONKey (Identity a) where+    toJSONKey = contramapToJSONKeyFunction runIdentity toJSONKey+    toJSONKeyList = contramapToJSONKeyFunction (map runIdentity) toJSONKeyList+++instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Compose f g) where+    liftToJSON tv tvl (Compose x) = liftToJSON g gl x+      where+        g = liftToJSON tv tvl+        gl = liftToJSONList tv tvl+    {-# INLINE liftToJSON #-}++    liftToJSONList te tel xs = liftToJSONList g gl (map getCompose xs)+      where+        g = liftToJSON te tel+        gl = liftToJSONList te tel+    {-# INLINE liftToJSONList #-}++    liftToEncoding te tel (Compose x) = liftToEncoding g gl x+      where+        g = liftToEncoding te tel+        gl = liftToEncodingList te tel+    {-# INLINE liftToEncoding #-}++    liftToEncodingList te tel xs = liftToEncodingList g gl (map getCompose xs)+      where+        g = liftToEncoding te tel+        gl = liftToEncodingList te tel+    {-# INLINE liftToEncodingList #-}++instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Compose f g a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toJSONList = liftToJSONList toJSON toJSONList+    {-# INLINE toJSONList #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++    toEncodingList = liftToEncodingList toEncoding toEncodingList+    {-# INLINE toEncodingList #-}+++instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Product f g) where+    liftToJSON tv tvl (Pair x y) = liftToJSON2 tx txl ty tyl (x, y)+      where+        tx = liftToJSON tv tvl+        txl = liftToJSONList tv tvl+        ty = liftToJSON tv tvl+        tyl = liftToJSONList tv tvl++    liftToEncoding te tel (Pair x y) = liftToEncoding2 tx txl ty tyl (x, y)+      where+        tx = liftToEncoding te tel+        txl = liftToEncodingList te tel+        ty = liftToEncoding te tel+        tyl = liftToEncodingList te tel++instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Product f g a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Sum f g) where+    liftToJSON tv tvl (InL x) = Object $ H.singleton "InL" (liftToJSON tv tvl x)+    liftToJSON tv tvl (InR y) = Object $ H.singleton "InR" (liftToJSON tv tvl y)++    liftToEncoding te tel (InL x) = E.pairs $ E.pair "InL" $ liftToEncoding te tel x+    liftToEncoding te tel (InR y) = E.pairs $ E.pair "InR" $ liftToEncoding te tel y++instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Sum f g a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- containers+-------------------------------------------------------------------------------++instance ToJSON1 Seq.Seq where+    liftToJSON t _ = listValue t . toList+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = listEncoding t . toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (Seq.Seq a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON1 Set.Set where+    liftToJSON t _ = listValue t . Set.toList+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = listEncoding t . Set.toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (Set.Set a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON IntSet.IntSet where+    toJSON = toJSON . IntSet.toList+    {-# INLINE toJSON #-}++    toEncoding = toEncoding . IntSet.toList+    {-# INLINE toEncoding #-}+++instance ToJSON1 IntMap.IntMap where+    liftToJSON t tol = liftToJSON to' tol' . IntMap.toList+      where+        to'  = liftToJSON2     toJSON toJSONList t tol+        tol' = liftToJSONList2 toJSON toJSONList t tol+    {-# INLINE liftToJSON #-}++    liftToEncoding t tol = liftToEncoding to' tol' . IntMap.toList+      where+        to'  = liftToEncoding2     toEncoding toEncodingList t tol+        tol' = liftToEncodingList2 toEncoding toEncodingList t tol+    {-# INLINE liftToEncoding #-}++instance ToJSON a => ToJSON (IntMap.IntMap a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSONKey k => ToJSON1 (M.Map k) where+    liftToJSON g _ = case toJSONKey of+        ToJSONKeyText f _ -> Object . mapHashKeyVal f g+        ToJSONKeyValue  f _ -> Array . V.fromList . map (toJSONPair f g) . M.toList+    {-# INLINE liftToJSON #-}++    liftToEncoding g _ = case toJSONKey of+        ToJSONKeyText _ f -> dict f g M.foldrWithKey+        ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . M.toList+      where+        pairEncoding f (a, b) = E.list id [f a, g b]+    {-# INLINE liftToEncoding #-}+++instance (ToJSON v, ToJSONKey k) => ToJSON (M.Map k v) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON1 Tree.Tree where+    liftToJSON t tol = go+      where+        go (Tree.Node root branches) =+            liftToJSON2 t tol to' tol' (root, branches)++        to' = liftToJSON go (listValue go)+        tol' = liftToJSONList go (listValue go)+    {-# INLINE liftToJSON #-}++    liftToEncoding t tol = go+      where+        go (Tree.Node root branches) =+            liftToEncoding2 t tol to' tol' (root, branches)++        to' = liftToEncoding go (listEncoding go)+        tol' = liftToEncodingList go (listEncoding go)+    {-# INLINE liftToEncoding #-}++instance (ToJSON v) => ToJSON (Tree.Tree v) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++-------------------------------------------------------------------------------+-- vector+-------------------------------------------------------------------------------++instance ToJSON1 Vector where+    liftToJSON t _ = Array . V.map t+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ =  listEncoding t . V.toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (Vector a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++encodeVector :: (ToJSON a, VG.Vector v a) => v a -> Encoding+encodeVector = listEncoding toEncoding . VG.toList+{-# INLINE encodeVector #-}++vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value+vectorToJSON = Array . V.map toJSON . V.convert+{-# INLINE vectorToJSON #-}++instance (Storable a, ToJSON a) => ToJSON (VS.Vector a) where+    toJSON = vectorToJSON+    {-# INLINE toJSON #-}++    toEncoding = encodeVector+    {-# INLINE toEncoding #-}+++instance (VP.Prim a, ToJSON a) => ToJSON (VP.Vector a) where+    toJSON = vectorToJSON+    {-# INLINE toJSON #-}++    toEncoding = encodeVector+    {-# INLINE toEncoding #-}+++instance (VG.Vector VU.Vector a, ToJSON a) => ToJSON (VU.Vector a) where+    toJSON = vectorToJSON+    {-# INLINE toJSON #-}++    toEncoding = encodeVector+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- unordered-containers+-------------------------------------------------------------------------------++instance ToJSON1 HashSet.HashSet where+    liftToJSON t _ = listValue t . HashSet.toList+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = listEncoding t . HashSet.toList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a) => ToJSON (HashSet.HashSet a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSONKey k => ToJSON1 (H.HashMap k) where+    liftToJSON g _ = case toJSONKey of+        ToJSONKeyText f _ -> Object . mapKeyVal f g+        ToJSONKeyValue f _ -> Array . V.fromList . map (toJSONPair f g) . H.toList+    {-# INLINE liftToJSON #-}++    -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> H.HashMap k a -> Encoding+    liftToEncoding g _ = case toJSONKey of+        ToJSONKeyText _ f -> dict f g H.foldrWithKey+        ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . H.toList+      where+        pairEncoding f (a, b) = E.list id [f a, g b]+    {-# INLINE liftToEncoding #-}++instance (ToJSON v, ToJSONKey k) => ToJSON (H.HashMap k v) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- aeson+-------------------------------------------------------------------------------++instance ToJSON Value where+    toJSON a = a+    {-# INLINE toJSON #-}++    toEncoding = E.value+    {-# INLINE toEncoding #-}++instance ToJSON DotNetTime where+    toJSON = toJSON . dotNetTime++    toEncoding = toEncoding . dotNetTime++dotNetTime :: DotNetTime -> String+dotNetTime (DotNetTime t) = secs ++ formatMillis t ++ ")/"+  where secs  = formatTime defaultTimeLocale "/Date(%s" t++formatMillis :: (FormatTime t) => t -> String+formatMillis = take 3 . formatTime defaultTimeLocale "%q"++-------------------------------------------------------------------------------+-- time+-------------------------------------------------------------------------------++instance ToJSON Day where+    toJSON     = stringEncoding . E.day+    toEncoding = E.day++instance ToJSONKey Day where+    toJSONKey = toJSONKeyTextEnc E.day+++instance ToJSON TimeOfDay where+    toJSON     = stringEncoding . E.timeOfDay+    toEncoding = E.timeOfDay++instance ToJSONKey TimeOfDay where+    toJSONKey = toJSONKeyTextEnc E.timeOfDay+++instance ToJSON LocalTime where+    toJSON     = stringEncoding . E.localTime+    toEncoding = E.localTime++instance ToJSONKey LocalTime where+    toJSONKey = toJSONKeyTextEnc E.localTime+++instance ToJSON ZonedTime where+    toJSON     = stringEncoding . E.zonedTime+    toEncoding = E.zonedTime++instance ToJSONKey ZonedTime where+    toJSONKey = toJSONKeyTextEnc E.zonedTime+++instance ToJSON UTCTime where+    toJSON     = stringEncoding . E.utcTime+    toEncoding = E.utcTime++instance ToJSONKey UTCTime where+    toJSONKey = toJSONKeyTextEnc E.utcTime++-- | Encode something t a JSON string.+stringEncoding :: Encoding' Text -> Value+stringEncoding = String+    . T.dropAround (== '"')+    . T.decodeLatin1+    . lazyToStrictByteString+    . E.encodingToLazyByteString+{-# INLINE stringEncoding #-}++instance ToJSON NominalDiffTime where+    toJSON = Number . realToFrac+    {-# INLINE toJSON #-}++    toEncoding = E.scientific . realToFrac+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- base Monoid/Semigroup+-------------------------------------------------------------------------------++instance ToJSON1 Dual where+    liftToJSON t _ = t . getDual+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ = t . getDual+    {-# INLINE liftToEncoding #-}++instance ToJSON a => ToJSON (Dual a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON1 First where+    liftToJSON t to' = liftToJSON t to' . getFirst+    {-# INLINE liftToJSON #-}++    liftToEncoding t to' = liftToEncoding t to' . getFirst+    {-# INLINE liftToEncoding #-}++instance ToJSON a => ToJSON (First a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSON1 Last where+    liftToJSON t to' = liftToJSON t to' . getLast+    {-# INLINE liftToJSON #-}++    liftToEncoding t to' = liftToEncoding t to' . getLast+    {-# INLINE liftToEncoding #-}++instance ToJSON a => ToJSON (Last a) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- tagged+-------------------------------------------------------------------------------++instance ToJSON (Proxy a) where+    toJSON _ = Null+    {-# INLINE toJSON #-}++    toEncoding _ = E.null_+    {-# INLINE toEncoding #-}+++instance ToJSON1 (Tagged a) where+    liftToJSON t _ (Tagged x) = t x+    {-# INLINE liftToJSON #-}++    liftToEncoding t _ (Tagged x) = t x+    {-# INLINE liftToEncoding #-}++instance ToJSON b => ToJSON (Tagged a b) where+    toJSON = toJSON1+    {-# INLINE toJSON #-}++    toEncoding = toEncoding1+    {-# INLINE toEncoding #-}+++instance ToJSONKey b => ToJSONKey (Tagged a b) where+    toJSONKey = contramapToJSONKeyFunction unTagged toJSONKey+    toJSONKeyList = contramapToJSONKeyFunction (fmap unTagged) toJSONKeyList++-------------------------------------------------------------------------------+-- Instances for converting t map keys+-------------------------------------------------------------------------------++instance (ToJSON a, ToJSON b) => ToJSONKey (a,b)+instance (ToJSON a, ToJSON b, ToJSON c) => ToJSONKey (a,b,c)+instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSONKey (a,b,c,d)++instance ToJSONKey Char where+    toJSONKey = ToJSONKeyText T.singleton (E.string . (:[]))+    toJSONKeyList = toJSONKeyText T.pack++instance (ToJSONKey a, ToJSON a) => ToJSONKey [a] where+    toJSONKey = toJSONKeyList++-------------------------------------------------------------------------------+-- Tuple instances+-------------------------------------------------------------------------------++instance ToJSON2 (,) where+    liftToJSON2 toA _ toB _ (a, b) = Array $ V.create $ do+        mv <- VM.unsafeNew 2+        VM.unsafeWrite mv 0 (toA a)+        VM.unsafeWrite mv 1 (toB b)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toA _ toB _ (a, b) = E.list id [toA a, toB b]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a) => ToJSON1 ((,) a) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b) => ToJSON (a, b) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a) => ToJSON2 ((,,) a) where+    liftToJSON2 toB _ toC _ (a, b, c) = Array $ V.create $ do+        mv <- VM.unsafeNew 3+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toB b)+        VM.unsafeWrite mv 2 (toC c)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toB _ toC _ (a, b, c) = E.list id+      [ toEncoding a+      , toB b+      , toC c+      ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b) => ToJSON1 ((,,) a b) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON (a, b, c) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b) => ToJSON2 ((,,,) a b) where+    liftToJSON2 toC _ toD _ (a, b, c, d) = Array $ V.create $ do+        mv <- VM.unsafeNew 4+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toC c)+        VM.unsafeWrite mv 3 (toD d)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toC _ toD _ (a, b, c, d) = E.list id+      [ toEncoding a+      , toEncoding b+      , toC c+      , toD d+      ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON1 ((,,,) a b c) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON (a, b, c, d) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON2 ((,,,,) a b c) where+    liftToJSON2 toD _ toE _ (a, b, c, d, e) = Array $ V.create $ do+        mv <- VM.unsafeNew 5+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toD d)+        VM.unsafeWrite mv 4 (toE e)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toD _ toE _ (a, b, c, d, e) = E.list id+      [ toEncoding a+      , toEncoding b+      , toEncoding c+      , toD d+      , toE e+      ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON1 ((,,,,) a b c d) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON (a, b, c, d, e) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON2 ((,,,,,) a b c d) where+    liftToJSON2 toE _ toF _ (a, b, c, d, e, f) = Array $ V.create $ do+        mv <- VM.unsafeNew 6+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toE e)+        VM.unsafeWrite mv 5 (toF f)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toE _ toF _ (a, b, c, d, e, f) = E.list id+      [ toEncoding a+      , toEncoding b+      , toEncoding c+      , toEncoding d+      , toE e+      , toF f+      ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON1 ((,,,,,) a b c d e) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON (a, b, c, d, e, f) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON2 ((,,,,,,) a b c d e) where+    liftToJSON2 toF _ toG _ (a, b, c, d, e, f, g) = Array $ V.create $ do+        mv <- VM.unsafeNew 7+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toF f)+        VM.unsafeWrite mv 6 (toG g)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toF _ toG _ (a, b, c, d, e, f, g) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toF f+        , toG g+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON1 ((,,,,,,) a b c d e f) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON (a, b, c, d, e, f, g) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON2 ((,,,,,,,) a b c d e f) where+    liftToJSON2 toG _ toH _ (a, b, c, d, e, f, g, h) = Array $ V.create $ do+        mv <- VM.unsafeNew 8+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toG g)+        VM.unsafeWrite mv 7 (toH h)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toG _ toH _ (a, b, c, d, e, f, g, h) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toG g+        , toH h+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON1 ((,,,,,,,) a b c d e f g) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h) => ToJSON (a, b, c, d, e, f, g, h) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON2 ((,,,,,,,,) a b c d e f g) where+    liftToJSON2 toH _ toI _ (a, b, c, d, e, f, g, h, i) = Array $ V.create $ do+        mv <- VM.unsafeNew 9+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toH h)+        VM.unsafeWrite mv 8 (toI i)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toH _ toI _ (a, b, c, d, e, f, g, h, i) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toH h+        , toI i+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h) => ToJSON1 ((,,,,,,,,) a b c d e f g h) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i) => ToJSON (a, b, c, d, e, f, g, h, i) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h) => ToJSON2 ((,,,,,,,,,) a b c d e f g h) where+    liftToJSON2 toI _ toJ _ (a, b, c, d, e, f, g, h, i, j) = Array $ V.create $ do+        mv <- VM.unsafeNew 10+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toI i)+        VM.unsafeWrite mv 9 (toJ j)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toI _ toJ _ (a, b, c, d, e, f, g, h, i, j) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toI i+        , toJ j+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i) => ToJSON1 ((,,,,,,,,,) a b c d e f g h i) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j) => ToJSON (a, b, c, d, e, f, g, h, i, j) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i) => ToJSON2 ((,,,,,,,,,,) a b c d e f g h i) where+    liftToJSON2 toJ _ toK _ (a, b, c, d, e, f, g, h, i, j, k) = Array $ V.create $ do+        mv <- VM.unsafeNew 11+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toJSON i)+        VM.unsafeWrite mv 9 (toJ j)+        VM.unsafeWrite mv 10 (toK k)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toJ _ toK _ (a, b, c, d, e, f, g, h, i, j, k) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toEncoding i+        , toJ j+        , toK k+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j) => ToJSON1 ((,,,,,,,,,,) a b c d e f g h i j) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k) => ToJSON (a, b, c, d, e, f, g, h, i, j, k) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j) => ToJSON2 ((,,,,,,,,,,,) a b c d e f g h i j) where+    liftToJSON2 toK _ toL _ (a, b, c, d, e, f, g, h, i, j, k, l) = Array $ V.create $ do+        mv <- VM.unsafeNew 12+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toJSON i)+        VM.unsafeWrite mv 9 (toJSON j)+        VM.unsafeWrite mv 10 (toK k)+        VM.unsafeWrite mv 11 (toL l)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toK _ toL _ (a, b, c, d, e, f, g, h, i, j, k, l) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toEncoding i+        , toEncoding j+        , toK k+        , toL l+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k) => ToJSON1 ((,,,,,,,,,,,) a b c d e f g h i j k) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l) => ToJSON (a, b, c, d, e, f, g, h, i, j, k, l) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k) => ToJSON2 ((,,,,,,,,,,,,) a b c d e f g h i j k) where+    liftToJSON2 toL _ toM _ (a, b, c, d, e, f, g, h, i, j, k, l, m) = Array $ V.create $ do+        mv <- VM.unsafeNew 13+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toJSON i)+        VM.unsafeWrite mv 9 (toJSON j)+        VM.unsafeWrite mv 10 (toJSON k)+        VM.unsafeWrite mv 11 (toL l)+        VM.unsafeWrite mv 12 (toM m)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toL _ toM _ (a, b, c, d, e, f, g, h, i, j, k, l, m) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toEncoding i+        , toEncoding j+        , toEncoding k+        , toL l+        , toM m+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l) => ToJSON1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m) => ToJSON (a, b, c, d, e, f, g, h, i, j, k, l, m) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l) => ToJSON2 ((,,,,,,,,,,,,,) a b c d e f g h i j k l) where+    liftToJSON2 toM _ toN _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = Array $ V.create $ do+        mv <- VM.unsafeNew 14+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toJSON i)+        VM.unsafeWrite mv 9 (toJSON j)+        VM.unsafeWrite mv 10 (toJSON k)+        VM.unsafeWrite mv 11 (toJSON l)+        VM.unsafeWrite mv 12 (toM m)+        VM.unsafeWrite mv 13 (toN n)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toM _ toN _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toEncoding i+        , toEncoding j+        , toEncoding k+        , toEncoding l+        , toM m+        , toN n+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m) => ToJSON1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m, ToJSON n) => ToJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m) => ToJSON2 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m) where+    liftToJSON2 toN _ toO _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = Array $ V.create $ do+        mv <- VM.unsafeNew 15+        VM.unsafeWrite mv 0 (toJSON a)+        VM.unsafeWrite mv 1 (toJSON b)+        VM.unsafeWrite mv 2 (toJSON c)+        VM.unsafeWrite mv 3 (toJSON d)+        VM.unsafeWrite mv 4 (toJSON e)+        VM.unsafeWrite mv 5 (toJSON f)+        VM.unsafeWrite mv 6 (toJSON g)+        VM.unsafeWrite mv 7 (toJSON h)+        VM.unsafeWrite mv 8 (toJSON i)+        VM.unsafeWrite mv 9 (toJSON j)+        VM.unsafeWrite mv 10 (toJSON k)+        VM.unsafeWrite mv 11 (toJSON l)+        VM.unsafeWrite mv 12 (toJSON m)+        VM.unsafeWrite mv 13 (toN n)+        VM.unsafeWrite mv 14 (toO o)+        return mv+    {-# INLINE liftToJSON2 #-}++    liftToEncoding2 toN _ toO _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = E.list id+        [ toEncoding a+        , toEncoding b+        , toEncoding c+        , toEncoding d+        , toEncoding e+        , toEncoding f+        , toEncoding g+        , toEncoding h+        , toEncoding i+        , toEncoding j+        , toEncoding k+        , toEncoding l+        , toEncoding m+        , toN n+        , toO o+        ]+    {-# INLINE liftToEncoding2 #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m, ToJSON n) => ToJSON1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) where+    liftToJSON = liftToJSON2 toJSON toJSONList+    {-# INLINE liftToJSON #-}+    liftToEncoding = liftToEncoding2 toEncoding toEncodingList+    {-# INLINE liftToEncoding #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m, ToJSON n, ToJSON o) => ToJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+    toJSON = toJSON2+    {-# INLINE toJSON #-}+    toEncoding = toEncoding2+    {-# INLINE toEncoding #-}++-------------------------------------------------------------------------------+-- pre-bytestring-0.10 compatibility+-------------------------------------------------------------------------------++{-# INLINE lazyToStrictByteString #-}+lazyToStrictByteString :: L.ByteString -> S.ByteString+#if MIN_VERSION_bytestring(0,10,0)+lazyToStrictByteString = L.toStrict+#else+lazyToStrictByteString = packChunks++-- packChunks is taken from the blaze-builder package.++-- | Pack the chunks of a lazy bytestring into a single strict bytestring.+packChunks :: L.ByteString -> S.ByteString+packChunks lbs = do+    S.unsafeCreate (fromIntegral $ L.length lbs) (copyChunks lbs)+  where+    copyChunks !L.Empty                         !_pf = return ()+    copyChunks !(L.Chunk (S.PS fpbuf o l) lbs') !pf  = do+        withForeignPtr fpbuf $ \pbuf ->+            copyBytes pf (pbuf `plusPtr` o) l+        copyChunks lbs' (pf `plusPtr` l)+#endif
aeson.cabal view
@@ -1,5 +1,5 @@ name:            aeson-version:         0.11.3.0+version:         1.0.0.0 license:         BSD3 license-file:    LICENSE category:        Text, Web, JSON@@ -8,7 +8,7 @@ author:          Bryan O'Sullivan <bos@serpentine.com> maintainer:      Bryan O'Sullivan <bos@serpentine.com> stability:       experimental-tested-with:     GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.2+tested-with:     GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1 synopsis:        Fast JSON parsing and encoding cabal-version:   >= 1.10 homepage:        https://github.com/bos/aeson@@ -58,72 +58,92 @@   default: False   manual: True -flag old-locale-  description: If false then depend on time >= 1.5.-               .-               If true then depend on time < 1.5 together with old-locale.+flag fast+  description: compile without optimizations   default: False+  manual: True +flag bytestring-builder+  description: Depend on the bytestring-builder package for backwards compatibility.+  default: False+  manual: False+ library   default-language: Haskell2010    exposed-modules:     Data.Aeson-    Data.Aeson.Encode-    Data.Aeson.Internal-    Data.Aeson.Internal.Time+    Data.Aeson.Encoding     Data.Aeson.Parser+    Data.Aeson.Text     Data.Aeson.Types     Data.Aeson.TH +    Data.Aeson.Encoding.Internal+    Data.Aeson.Internal+    Data.Aeson.Internal.Time++  -- Deprecated modules+  exposed-modules:+    Data.Aeson.Encode+   other-modules:-    Data.Aeson.Encode.Builder-    Data.Aeson.Encode.Functions-    Data.Aeson.Functions+    Data.Aeson.Encoding.Builder+    Data.Aeson.Internal.Functions     Data.Aeson.Parser.Internal     Data.Aeson.Parser.Time-    Data.Aeson.Types.Class+    Data.Aeson.Types.FromJSON     Data.Aeson.Types.Generic-    Data.Aeson.Types.Instances+    Data.Aeson.Types.ToJSON+    Data.Aeson.Types.Class     Data.Aeson.Types.Internal    build-depends:     attoparsec >= 0.13.0.1,     base >= 4.5 && < 5,-    bytestring >= 0.10.4.0,-    containers,-    deepseq,+    base-compat >= 0.9.1 && < 0.10,+    containers >= 0.2.4.1,+    deepseq >= 1.3,     dlist >= 0.2,-    fail == 4.9.*,     ghc-prim >= 0.2,     hashable >= 1.1.2.0,-    mtl,-    scientific >= 0.3.1 && < 0.4,-    syb,+    scientific >= 0.3.4.7 && < 0.4,     tagged >=0.8.3 && <0.9,     template-haskell >= 2.7,     text >= 1.1.1.0,-    transformers,+    time >= 1.1.1.4,+    time-locale-compat >= 0.1.1 && < 0.2,     unordered-containers >= 0.2.5.0,     vector >= 0.8 +  if flag(bytestring-builder)+    build-depends: bytestring >= 0.9 && < 0.10.4,+                   bytestring-builder >= 0.10.4 && < 1+  else+    build-depends: bytestring >= 0.10.4+   if !impl(ghc >= 8.0)-    -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9-    build-depends: semigroups >= 0.16.1 && < 0.19+    -- `Data.Semigroup` and `Control.Monad.Fail` and `Control.Monad.IO.Class` are available in base only since GHC 8.0 / base 4.9+    build-depends:+      semigroups >= 0.18.2 && < 0.19,+      transformers >= 0.2.2.0,+      transformers-compat >= 0.3,+      fail == 4.9.*    if !impl(ghc >= 7.10)     -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8-    build-depends: nats >=1 && <1.2+    build-depends: nats >= 1 && < 1.2 -  if flag(old-locale)-    build-depends: time < 1.5, old-locale-  else-    build-depends: time >= 1.5+  ghc-options: -Wall    if flag(developer)+    ghc-options: -Werror     ghc-prof-options: -auto-all -  ghc-options: -O2 -Wall+  if flag(fast)+    ghc-options: -O0+  else+    ghc-options: -O2    include-dirs: include @@ -144,20 +164,24 @@     Properties     Types     UnitTests+    UnitTests.NullaryConstructors    ghc-options: -Wall -threaded -rtsopts    build-depends:     HUnit,-    QuickCheck >= 2.7 && <2.10,+    QuickCheck >= 2.7 && <2.8.3,     aeson,     attoparsec,     base,-    base-orphans >=0.5.3 && <0.6,-    bytestring,+    base-compat,+    base-orphans >= 0.5.3 && <0.6,     containers,+    dlist,+    generic-deriving >= 1.10 && < 1.11,     ghc-prim >= 0.2,-    hashable >= 1.1.2.0,+    hashable >= 1.2.4.0,+    scientific,     tagged,     template-haskell,     test-framework,@@ -165,20 +189,28 @@     test-framework-quickcheck2,     text,     time,+    time-locale-compat,     unordered-containers,     vector,     quickcheck-instances >=0.3.12 -  if !impl(ghc >= 8.0)-    build-depends: semigroups >= 0.16.1 && < 0.19--  if flag(old-locale)-    build-depends: time < 1.5, old-locale+  if flag(bytestring-builder)+    build-depends: bytestring >= 0.9 && < 0.10.4,+                   bytestring-builder >= 0.10.4 && < 1   else-    build-depends: time >= 1.5+    build-depends: bytestring >= 0.10.4 +  if !impl(ghc >= 8.0)+    build-depends:+      semigroups >= 0.18.2 && < 0.19,+      transformers >= 0.2.2.0,+      transformers-compat >= 0.3+   if !impl(ghc >= 7.10)     build-depends: nats >=1 && <1.2++  if impl(ghc >= 7.8)+    build-depends: hashable-time >= 0.2 && <0.3  source-repository head   type:     git
benchmarks/AesonCompareAutoInstances.hs view
@@ -1,24 +1,22 @@-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, TemplateHaskell #-}--module Main where+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TemplateHaskell #-} ---------------------------------------------------------------------------------+module Main (main) where -import Criterion.Main hiding (defaultOptions)+import Prelude ()+import Prelude.Compat  import Control.DeepSeq (NFData, rnf, deepseq)--import Data.Typeable (Typeable)+import Criterion.Main hiding (defaultOptions)+import Data.Aeson.Encode+import Data.Aeson.TH+import Data.Aeson.Types import Data.Data (Data)+import Data.Typeable (Typeable) import GHC.Generics (Generic)--import Data.Aeson.Types-import Data.Aeson.TH-import qualified Data.Aeson.Generic as G (fromJSON, toJSON)--import Data.Aeson.Encode- import Options+import qualified Data.Aeson.Generic as G (fromJSON, toJSON)  -------------------------------------------------------------------------------- 
benchmarks/AesonEncode.hs view
@@ -1,5 +1,12 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-} +module Main (main) where++import Prelude ()+import Prelude.Compat++import Control.DeepSeq import Control.Exception import Control.Monad import Data.Aeson@@ -9,7 +16,6 @@ import System.Environment (getArgs) import System.IO import qualified Data.ByteString as B-import Control.DeepSeq  main :: IO () main = do@@ -17,6 +23,7 @@   let (cnt,args) = case args0 of         (i:c:a) | all isDigit i && all isDigit c -> (c,a)         (c:a) -> (c,a)+        [] -> error "Unexpected empty list"   let count = read cnt :: Int   forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do     putStrLn $ arg ++ ":"
+ benchmarks/AesonFoldable.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PackageImports #-}++module Main (main) where++import Criterion.Main++import Prelude ()+import Prelude.Compat++import Data.Foldable (toList)+import qualified "aeson" Data.Aeson as A+import qualified "aeson-benchmarks" Data.Aeson as B+import qualified Data.Sequence as S+import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as U++-------------------------------------------------------------------------------+-- List+-------------------------------------------------------------------------------++newtype L f = L { getL :: f Int }++instance Foldable f => B.ToJSON (L f) where+    toJSON = error "do not use this"+    toEncoding = B.toEncoding . toList . getL++instance Foldable f => A.ToJSON (L f) where+    toJSON = error "do not use this"+    toEncoding = A.toEncoding . toList . getL++-------------------------------------------------------------------------------+-- Foldable+-------------------------------------------------------------------------------++newtype F f = F { getF :: f Int }++instance Foldable f => B.ToJSON (F f) where+    toJSON = error "do not use this"+    toEncoding = B.foldable . getF++instance Foldable f => A.ToJSON (F f) where+    toJSON = error "do not use this"+    toEncoding = A.foldable . getF++-------------------------------------------------------------------------------+-- Values+-------------------------------------------------------------------------------++valueList :: [Int]+valueList = [1..1000]++valueSeq :: S.Seq Int+valueSeq = S.fromList valueList++valueVector :: V.Vector Int+valueVector = V.fromList valueList++valueUVector :: U.Vector Int+valueUVector = U.fromList valueList++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++benchEncodeA+    :: A.ToJSON a+    => String+    -> a+    -> Benchmark+benchEncodeA name val+    = bench ("A " ++ name) $ nf A.encode val++benchEncodeB+    :: B.ToJSON a+    => String+    -> a+    -> Benchmark+benchEncodeB name val+    = bench ("B " ++ name) $ nf B.encode val++main :: IO ()+main =  defaultMain+    [ bgroup "encode"+        [ bgroup "List"+            [ benchEncodeB "-"     valueList+            , benchEncodeB "L" $ L valueList+            , benchEncodeB "F" $ F valueList+            , benchEncodeA "-"     valueList+            , benchEncodeA "L" $ L valueList+            , benchEncodeA "F" $ F valueList+            ]+        , bgroup "Seq"+            [ benchEncodeB "-"     valueSeq+            , benchEncodeB "L" $ L valueSeq+            , benchEncodeB "F" $ F valueSeq+            , benchEncodeA "-"     valueSeq+            , benchEncodeA "L" $ L valueSeq+            , benchEncodeA "F" $ F valueSeq+            ]+        , bgroup "Vector"+            [ benchEncodeB "-"     valueVector+            , benchEncodeB "L" $ L valueVector+            , benchEncodeB "F" $ F valueVector+            , benchEncodeA "-"     valueVector+            , benchEncodeA "L" $ L valueVector+            , benchEncodeA "F" $ F valueVector+            ]+        , bgroup "Vector.Unboxed"+            [ benchEncodeB "-"     valueUVector+            , benchEncodeA "-"     valueUVector+            ]+        ]+    ]
+ benchmarks/AesonMap.hs view
@@ -0,0 +1,231 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PackageImports #-}+{-# LANGUAGE RankNTypes #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Main (main) where++import Prelude ()+import Prelude.Compat++import Control.DeepSeq+import Criterion.Main+import Data.Hashable+import Data.Proxy (Proxy (..))+import Data.Tagged (Tagged (..))+import qualified "aeson" Data.Aeson as A+import qualified "aeson-benchmarks" Data.Aeson as B+import qualified "aeson-benchmarks" Data.Aeson.Types as B (fromJSONKeyCoerce)+import qualified Data.ByteString.Lazy as LBS+import qualified Data.HashMap.Strict as HM+import qualified Data.Map as M+import qualified Data.Text as T++value :: Int -> HM.HashMap T.Text T.Text+value n = HM.fromList $ map f [1..n]+  where+    f m = let t = T.pack (show m) in (t, t)++-------------------------------------------------------------------------------+-- Orphans+-------------------------------------------------------------------------------++instance Hashable b => Hashable (Tagged a b) where+    hashWithSalt salt (Tagged a) = hashWithSalt salt a++-------------------------------------------------------------------------------+-- Text+-------------------------------------------------------------------------------++newtype T1 = T1 T.Text+  deriving (Eq, Ord)++instance NFData T1 where+    rnf (T1 t) = rnf t+instance Hashable T1 where+    hashWithSalt salt (T1 t) = hashWithSalt salt t++instance B.FromJSON T1 where+    parseJSON = B.withText "T1" $ pure . T1+instance B.FromJSONKey T1 where+    fromJSONKey = B.FromJSONKeyText T1++-------------------------------------------------------------------------------+-- Coerce+-------------------------------------------------------------------------------++newtype T2 = T2 T.Text+  deriving (Eq, Ord)++instance NFData T2 where+    rnf (T2 t) = rnf t+instance Hashable T2 where+    hashWithSalt salt (T2 t) = hashWithSalt salt t++instance B.FromJSON T2 where+    parseJSON = B.withText "T2" $ pure . T2+instance B.FromJSONKey T2 where+    fromJSONKey = B.fromJSONKeyCoerce++-------------------------------------------------------------------------------+-- TextParser+-------------------------------------------------------------------------------++newtype T3 = T3 T.Text+  deriving (Eq, Ord)++instance NFData T3 where+    rnf (T3 t) = rnf t+instance Hashable T3 where+    hashWithSalt salt (T3 t) = hashWithSalt salt t++instance B.FromJSON T3 where+    parseJSON = B.withText "T3" $ pure . T3+instance B.FromJSONKey T3 where+    fromJSONKey = B.FromJSONKeyTextParser (pure . T3)++-------------------------------------------------------------------------------+-- Values+-------------------------------------------------------------------------------++value10, value100, value1000, value10000 :: HM.HashMap T.Text T.Text+value10 = value 10+value100 = value 100+value1000 = value 1000+value10000 = value 10000++encodedValue10 :: LBS.ByteString+encodedValue10 = B.encode $ value10++encodedValue100 :: LBS.ByteString+encodedValue100 = B.encode $ value100++encodedValue1000 :: LBS.ByteString+encodedValue1000 = B.encode $ value1000++encodedValue10000 :: LBS.ByteString+encodedValue10000 = B.encode $ value10000++-------------------------------------------------------------------------------+-- Helpers+-------------------------------------------------------------------------------++decodeHMB+    :: (B.FromJSONKey k, Eq k, Hashable k)+    => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)+decodeHMB _ = B.decode++decodeHMA+    :: (A.FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)+    => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)+decodeHMA _ = A.decode++decodeMapB+    :: (B.FromJSONKey k, Ord k)+    => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)+decodeMapB _ = B.decode++decodeMapA+    :: (A.FromJSON (M.Map k T.Text), Ord k)+    => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)+decodeMapA _ = A.decode++proxyText :: Proxy T.Text+proxyText = Proxy++proxyT1 :: Proxy T1+proxyT1 = Proxy++proxyT2 :: Proxy T2+proxyT2 = Proxy++proxyT3 :: Proxy T3+proxyT3 = Proxy++proxyTagged :: Proxy a -> Proxy (Tagged () a)+proxyTagged _ = Proxy++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++benchDecodeHM+    :: String+    -> LBS.ByteString+    -> Benchmark+benchDecodeHM name val = bgroup name+    [  bench "Text"            $ nf (decodeHMB proxyText) val+    ,  bench "Identity"        $ nf (decodeHMB proxyT1)   val+    ,  bench "Coerce"          $ nf (decodeHMB proxyT2)   val+    ,  bench "Parser"          $ nf (decodeHMB proxyT3)   val+    ,  bench "aeson-0.11"      $ nf (decodeHMA proxyText) val+    ,  bench "Tagged Text"     $ nf (decodeHMB $ proxyTagged proxyText) val+    ,  bench "Tagged Identity" $ nf (decodeHMB $ proxyTagged proxyT1)   val+    ,  bench "Tagged Coerce"   $ nf (decodeHMB $ proxyTagged proxyT2)   val+    ,  bench "Tagged Parser"   $ nf (decodeHMB $ proxyTagged proxyT3)   val+    ]++benchDecodeMap+    :: String+    -> LBS.ByteString+    -> Benchmark+benchDecodeMap name val = bgroup name+    [  bench "Text"        $ nf (decodeMapB proxyText) val+    ,  bench "Identity"    $ nf (decodeMapB proxyT1)   val+    ,  bench "Coerce"      $ nf (decodeMapB proxyT2)   val+    ,  bench "Parser"      $ nf (decodeMapB proxyT3)   val+    ,  bench "aeson-0.11"  $ nf (decodeMapA proxyText) val+    ]++benchEncodeHM+    :: String+    -> HM.HashMap T.Text T.Text+    -> Benchmark+benchEncodeHM name val = bgroup name+    [ bench "Text"       $ nf B.encode val+    , bench "aeson-0.11" $ nf A.encode val+    ]++benchEncodeMap+    :: String+    -> HM.HashMap T.Text T.Text+    -> Benchmark+benchEncodeMap name val = bgroup name+    [ bench "Text"       $ nf B.encode val'+    , bench "aeson-0.11" $ nf A.encode val'+    ]+  where+    val' :: M.Map T.Text T.Text+    val' = M.fromList . HM.toList $ val++main :: IO ()+main = defaultMain+    [ bgroup "decode"+        [ bgroup "HashMap"+            [ benchDecodeHM "10"    encodedValue10+            , benchDecodeHM "100"   encodedValue100+            , benchDecodeHM "1000"  encodedValue1000+            , benchDecodeHM "10000" encodedValue10000+            ]+        , bgroup "Map"+            [ benchDecodeMap "10"    encodedValue10+            , benchDecodeMap "100"   encodedValue100+            , benchDecodeMap "1000"  encodedValue1000+            , benchDecodeMap "10000" encodedValue10000+            ]+        ]+    , bgroup "encode"+        [ bgroup "HashMap"+            [ benchEncodeHM "100"   value100+            , benchEncodeHM "1000"  value1000+            , benchEncodeHM "10000" value10000+            ]+        , bgroup "Map"+            [ benchEncodeMap "100"   value100+            , benchEncodeMap "1000"  value1000+            , benchEncodeMap "10000" value10000+            ]+        ]+    ]
benchmarks/AesonParse.hs view
@@ -1,8 +1,15 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PackageImports #-} +module Main (main) where++import Prelude ()+import Prelude.Compat++import "aeson-benchmarks" Data.Aeson import Control.Exception import Control.Monad-import Data.Aeson import Data.Attoparsec.ByteString (IResult(..), parseWith) import Data.Time.Clock import System.Environment (getArgs)
benchmarks/AesonTuples.hs view
@@ -1,9 +1,12 @@ module Main where ---------------------------------------------------------------------------------+module Main (main) where -import Criterion.Main+import Prelude ()+import Prelude.Compat+ import Control.DeepSeq (deepseq)+import Criterion.Main import Data.Aeson  --------------------------------------------------------------------------------
benchmarks/Compare.hs view
@@ -1,7 +1,11 @@+{-# LANGUAGE PackageImports #-} {-# LANGUAGE ScopedTypeVariables #-}  module Main (main) where +import Prelude ()+import Prelude.Compat+ import Compare.BufferBuilder () import Compare.JsonBuilder () import Criterion.Main@@ -10,8 +14,8 @@ import Twitter import Twitter.Manual () import Typed.Common+import qualified "aeson-benchmarks" Data.Aeson as Aeson import qualified Compare.JsonBench as JsonBench-import qualified Data.Aeson as Aeson  main :: IO () main =
benchmarks/Compare/BufferBuilder.hs view
@@ -1,11 +1,17 @@-{-# LANGUAGE OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++{-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Compare.BufferBuilder () where +import Prelude ()+import Prelude.Compat+ import Data.BufferBuilder.Json-import Data.Monoid ((<>)) import Data.Int (Int64)+import Data.Monoid ((<>)) import Prelude hiding (id) import Twitter import qualified Data.BufferBuilder.Utf8 as UB@@ -37,7 +43,7 @@     <> "metadata"          .= metadata     <> "to_user_id"        .= to_user_id     <> "text"              .= text-    <> "id"                .= id+    <> "id"                .= id_     <> "from_user_id"      .= from_user_id     <> "geo"               .= geo     <> "iso_language_code" .= iso_language_code
benchmarks/Compare/JsonBench.hs view
@@ -2,11 +2,17 @@ -- -- https://github.com/chadaustin/buffer-builder/blob/master/test.json -{-# LANGUAGE BangPatterns, OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash, ScopedTypeVariables #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Compare.JsonBench (benchmarks) where++import Prelude ()+import Prelude.Compat  import Control.DeepSeq (NFData(..)) import Criterion
benchmarks/Compare/JsonBuilder.hs view
@@ -1,8 +1,13 @@ {-# LANGUAGE RecordWildCards #-}++{-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Compare.JsonBuilder () where +import Prelude ()+import Prelude.Compat+ import Data.Json.Builder import Data.Monoid ((<>)) import Prelude hiding (id)@@ -36,7 +41,7 @@     row "metadata" metadata <>     row "to_user_id" to_user_id <>     row "text" text <>-    row "id" id <>+    row "id" id_ <>     row "from_user_id" from_user_id <>     row "geo" geo <>     row "iso_language_code" iso_language_code <>
benchmarks/CompareWithJSON.hs view
@@ -1,16 +1,21 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} +module Main (main) where++import Prelude ()+import Prelude.Compat+ import Blaze.ByteString.Builder (toLazyByteString) import Blaze.ByteString.Builder.Char.Utf8 (fromString) import Control.DeepSeq (NFData(rnf)) import Criterion.Main-import qualified Data.Aeson.Encode as A import qualified Data.Aeson as A+import qualified Data.Aeson.Text as A import qualified Data.ByteString.Lazy as BL-import qualified Text.JSON as J import qualified Data.Text.Lazy          as TL import qualified Data.Text.Lazy.Builder  as TLB import qualified Data.Text.Lazy.Encoding as TLE+import qualified Text.JSON as J  instance (NFData v) => NFData (J.JSObject v) where   rnf o = rnf (J.fromJSObject o)
benchmarks/Dates.hs view
@@ -1,4 +1,8 @@-import Control.Applicative ((<$>))+module Main (main) where++import Prelude ()+import Prelude.Compat+ import Criterion.Main import Data.Aeson (decode, encode) import Data.Time.Clock (UTCTime)
benchmarks/JsonParse.hs view
@@ -1,11 +1,17 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-orphans #-} +module Main (main) where++import Prelude ()+import Prelude.Compat+ import Control.DeepSeq import Control.Monad-import Text.JSON import Data.Time.Clock import System.Environment (getArgs)+import Text.JSON  instance NFData JSValue where     rnf JSNull = ()
benchmarks/Micro.hs view
@@ -1,10 +1,12 @@ module Main (main) where +import Prelude ()+import Prelude.Compat+ import Criterion.Main-import qualified Data.Aeson.Encode.Builder as AB+import qualified Data.Aeson.Encoding.Builder as AB import qualified Data.ByteString.Builder as B import qualified Data.Text as T-  main :: IO () main = do
benchmarks/Options.hs view
@@ -1,4 +1,7 @@-module Options where+module Options () where++import Prelude ()+import Prelude.Compat  import Data.Aeson.Types 
benchmarks/ReadFile.hs view
@@ -1,4 +1,10 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}++module Main (main) where++import Prelude ()+import Prelude.Compat  import Control.DeepSeq import Control.Exception
benchmarks/Typed.hs view
@@ -1,5 +1,8 @@ module Main (main) where +import Prelude ()+import Prelude.Compat+ import Criterion.Main import qualified Typed.Generic as Generic import qualified Typed.Manual as Manual
benchmarks/Typed/Common.hs view
@@ -1,10 +1,23 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE PackageImports #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}+ module Typed.Common (load) where -import Data.Aeson hiding (Result)+import Prelude ()+import Prelude.Compat+ import Data.ByteString.Lazy as L-import Control.Applicative-import System.IO import System.Exit+import System.IO++#ifndef HAS_BOTH_AESON_AND_BENCHMARKS+import Data.Aeson hiding (Result)+#else+import "aeson" Data.Aeson hiding (Result)+import qualified "aeson-benchmarks" Data.Aeson as B+#endif  load :: FromJSON a => FilePath -> IO a load fileName = do
benchmarks/Typed/Generic.hs view
@@ -1,29 +1,42 @@+{-# LANGUAGE PackageImports #-} module Typed.Generic (benchmarks) where -import Control.Applicative+import Prelude ()+import Prelude.Compat++import "aeson" Data.Aeson hiding (Result) import Criterion-import Data.Aeson hiding (Result)-import Data.ByteString.Builder as B import Data.ByteString.Lazy as L import Twitter.TH import Typed.Common+import qualified "aeson-benchmarks" Data.Aeson as B -encodeDirect :: Result -> L.ByteString-encodeDirect = encode+encodeDirectA :: Result -> L.ByteString+encodeDirectA = encode -encodeViaValue :: Result -> L.ByteString-encodeViaValue = encode . toJSON+encodeViaValueA :: Result -> L.ByteString+encodeViaValueA = encode . toJSON +encodeDirectB :: Result -> L.ByteString+encodeDirectB = B.encode++encodeViaValueB :: Result -> L.ByteString+encodeViaValueB = B.encode . B.toJSON+ benchmarks :: Benchmark benchmarks =   env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->   bgroup "generic" [       bgroup "direct" [-        bench "twitter100" $ nf encodeDirect twitter100-      , bench "jp100" $ nf encodeDirect jp100+        bench "twitter100"          $ nf encodeDirectB twitter100+      , bench "jp100"               $ nf encodeDirectB jp100+      , bench "twitter100 baseline" $ nf encodeDirectA twitter100+      , bench "jp100 baseline"      $ nf encodeDirectA jp100       ]     , bgroup "viaValue" [-        bench "twitter100" $ nf encodeViaValue twitter100-      , bench "jp100" $ nf encodeViaValue jp100+        bench "twitter100"          $ nf encodeViaValueB twitter100+      , bench "jp100"               $ nf encodeViaValueB jp100+      , bench "twitter100 baseline" $ nf encodeViaValueA twitter100+      , bench "jp100 baseline"      $ nf encodeViaValueA jp100       ]     ]
benchmarks/Typed/Manual.hs view
@@ -1,29 +1,42 @@+{-# LANGUAGE PackageImports #-} module Typed.Manual (benchmarks) where -import Control.Applicative+import Prelude ()+import Prelude.Compat++import "aeson" Data.Aeson hiding (Result) import Criterion-import Data.Aeson hiding (Result)-import Data.ByteString.Builder as B import Data.ByteString.Lazy as L import Twitter.Manual import Typed.Common+import qualified "aeson-benchmarks" Data.Aeson as B -encodeDirect :: Result -> L.ByteString-encodeDirect = encode+encodeDirectA :: Result -> L.ByteString+encodeDirectA = encode -encodeViaValue :: Result -> L.ByteString-encodeViaValue = encode . toJSON+encodeViaValueA :: Result -> L.ByteString+encodeViaValueA = encode . toJSON +encodeDirectB :: Result -> L.ByteString+encodeDirectB = B.encode++encodeViaValueB :: Result -> L.ByteString+encodeViaValueB = B.encode . B.toJSON+ benchmarks :: Benchmark benchmarks =   env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->   bgroup "manual" [       bgroup "direct" [-        bench "twitter100" $ nf encodeDirect twitter100-      , bench "jp100" $ nf encodeDirect jp100+        bench "twitter100"          $ nf encodeDirectB twitter100+      , bench "jp100"               $ nf encodeDirectB jp100+      , bench "twitter100 baseline" $ nf encodeDirectA twitter100+      , bench "jp100 baseline"      $ nf encodeDirectA jp100       ]     , bgroup "viaValue" [-        bench "twitter100" $ nf encodeViaValue twitter100-      , bench "jp100" $ nf encodeViaValue jp100+        bench "twitter100"          $ nf encodeViaValueB twitter100+      , bench "jp100"               $ nf encodeViaValueB jp100+      , bench "twitter100 baseline" $ nf encodeViaValueA twitter100+      , bench "jp100 baseline"      $ nf encodeViaValueA jp100       ]     ]
benchmarks/Typed/TH.hs view
@@ -1,29 +1,42 @@+{-# LANGUAGE PackageImports #-} module Typed.TH (benchmarks) where -import Control.Applicative+import Prelude ()+import Prelude.Compat++import "aeson" Data.Aeson hiding (Result) import Criterion-import Data.Aeson hiding (Result)-import Data.ByteString.Builder as B import Data.ByteString.Lazy as L import Twitter.TH import Typed.Common+import qualified "aeson-benchmarks" Data.Aeson as B -encodeDirect :: Result -> L.ByteString-encodeDirect = encode+encodeDirectA :: Result -> L.ByteString+encodeDirectA = encode -encodeViaValue :: Result -> L.ByteString-encodeViaValue = encode . toJSON+encodeViaValueA :: Result -> L.ByteString+encodeViaValueA = encode . toJSON +encodeDirectB :: Result -> L.ByteString+encodeDirectB = B.encode++encodeViaValueB :: Result -> L.ByteString+encodeViaValueB = B.encode . B.toJSON+ benchmarks :: Benchmark benchmarks =   env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->   bgroup "th" [       bgroup "direct" [-        bench "twitter100" $ nf encodeDirect twitter100-      , bench "jp100" $ nf encodeDirect jp100+        bench "twitter100"          $ nf encodeDirectB twitter100+      , bench "jp100"               $ nf encodeDirectB jp100+      , bench "twitter100 baseline" $ nf encodeDirectA twitter100+      , bench "jp100 baseline"      $ nf encodeDirectA jp100       ]     , bgroup "viaValue" [-        bench "twitter100" $ nf encodeViaValue twitter100-      , bench "jp100" $ nf encodeViaValue jp100+        bench "twitter100"          $ nf encodeViaValueA twitter100+      , bench "jp100"               $ nf encodeViaValueA jp100+      , bench "twitter100 baseline" $ nf encodeViaValueB twitter100+      , bench "jp100 baseline"      $ nf encodeViaValueB jp100       ]     ]
benchmarks/aeson-benchmarks.cabal view
@@ -4,37 +4,41 @@  cabal-version:       >=1.8 -flag old-locale-  description: If false then depend on time >= 1.5.-               .-               If true then depend on time < 1.5 together with old-locale.+flag bytestring-builder+  description: Depend on the bytestring-builder package for backwards compatibility.   default: False+  manual: False  library   hs-source-dirs: .. .    exposed-modules:     Data.Aeson-    Data.Aeson.Encode-    Data.Aeson.Encode.Builder-    Data.Aeson.Encode.Functions-    Data.Aeson.Functions+    Data.Aeson.Encoding+    Data.Aeson.Parser+    Data.Aeson.Text+    Data.Aeson.Types+    Data.Aeson.TH++    Data.Aeson.Encoding.Internal     Data.Aeson.Internal     Data.Aeson.Internal.Time-    Data.Aeson.Parser++    Data.Aeson.Encoding.Builder+    Data.Aeson.Internal.Functions     Data.Aeson.Parser.Internal     Data.Aeson.Parser.Time-    Data.Aeson.TH-    Data.Aeson.Types-    Data.Aeson.Types.Class+    Data.Aeson.Types.FromJSON     Data.Aeson.Types.Generic-    Data.Aeson.Types.Instances+    Data.Aeson.Types.ToJSON+    Data.Aeson.Types.Class     Data.Aeson.Types.Internal    build-depends:     attoparsec >= 0.13.0.1,     base == 4.*,-    bytestring >= 0.10.4.0,+    base-compat >= 0.9.1 && <0.10,+    time-locale-compat >=0.1.1 && <0.2,     containers,     deepseq,     dlist >= 0.2,@@ -42,7 +46,7 @@     ghc-prim >= 0.2,     hashable >= 1.1.2.0,     mtl,-    scientific >= 0.3.1 && < 0.4,+    scientific >= 0.3.4.7 && < 0.4,     syb,     tagged >=0.8.3 && <0.9,     template-haskell >= 2.4,@@ -52,14 +56,18 @@     unordered-containers >= 0.2.3.0,     vector >= 0.7.1 +  if flag(bytestring-builder)+    build-depends: bytestring >= 0.9 && < 0.10.4,+                   bytestring-builder >= 0.10.4 && < 1+  else+    build-depends: bytestring >= 0.10.4++  if impl(ghc >=7.8)+    cpp-options: -DHAS_COERCIBLE+   if !impl(ghc >= 8.0)     -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9-    build-depends: semigroups >= 0.16.1 && < 0.19--  if flag(old-locale)-    build-depends: time < 1.5, old-locale-  else-    build-depends: time >= 1.5+    build-depends: semigroups >= 0.18.2 && < 0.19    include-dirs: ../include @@ -73,6 +81,7 @@   build-depends:     aeson-benchmarks,     base,+    base-compat,     buffer-builder,     bytestring,     criterion >= 1.0,@@ -88,6 +97,7 @@   build-depends:     aeson-benchmarks,     base,+    base-compat,     bytestring,     criterion >= 1.0,     deepseq,@@ -98,22 +108,33 @@   main-is: Typed.hs   hs-source-dirs: ../examples .   ghc-options: -Wall -O2 -rtsopts+  -- We must help ourself in situations when there is both+  -- aeson and aeson-benchmakrs+  cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS   build-depends:+    aeson,     aeson-benchmarks,     base,-    bytestring,+    base-compat,     criterion >= 1.0,     deepseq,     ghc-prim,     text,     time +  if flag(bytestring-builder)+    build-depends: bytestring >= 0.9 && < 0.10.4,+                   bytestring-builder >= 0.10.4 && < 1+  else+    build-depends: bytestring >= 0.10.4+ executable aeson-benchmark-compare-with-json   main-is: CompareWithJSON.hs   ghc-options: -Wall -O2 -rtsopts   build-depends:     aeson-benchmarks,     base,+    base-compat,     blaze-builder,     bytestring,     criterion,@@ -128,6 +149,7 @@     aeson-benchmarks,     attoparsec,     base,+    base-compat,     bytestring,     deepseq,     time@@ -139,6 +161,7 @@     aeson-benchmarks,     attoparsec,     base,+    base-compat,     bytestring,     time @@ -147,6 +170,7 @@   ghc-options: -Wall -O2 -rtsopts   build-depends:     base,+    base-compat,     deepseq,     json,     time@@ -156,9 +180,45 @@   ghc-options: -Wall -O2 -rtsopts   build-depends:     base,+    base-compat,     bytestring,     criterion,     deepseq,     aeson-benchmarks,     text,     time++executable aeson-benchmark-map+  main-is: AesonMap.hs+  ghc-options: -Wall -O2 -rtsopts+  build-depends:+    aeson,+    aeson-benchmarks,+    base,+    base-compat,+    criterion >= 1.0,+    bytestring,+    containers,+    deepseq,+    hashable,+    tagged,+    text,+    unordered-containers++executable aeson-benchmark-foldable+  main-is: AesonFoldable.hs+  ghc-options: -Wall -O2 -rtsopts+  build-depends:+    aeson,+    aeson-benchmarks,+    base,+    base-compat,+    criterion >= 1.0,+    bytestring,+    containers,+    deepseq,+    hashable,+    tagged,+    text,+    unordered-containers,+    vector
changelog.md view
@@ -1,8 +1,80 @@ For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md). -### 0.11.3.0+# 1.0.0.0 -* Backported support for `Day`s BCE from aeson-1.1.0.0+Major enhancements:++* Introduced new `FromJSONKey` and `ToJSONKey` type classes that are+  used to encode maps without going through HashMap. This also allows arbitrary+  serialization of keys where a string-like key will encode into an object and+  other keys will encode into an array of key-value tuples.++* Added higher rank classes: `ToJSON1`, `ToJSON2`, `FromJSON1`, and+  `FromJSON2`.++* Added `Data.Aeson.Encoding` with functions to safely write `ToJSON`+  instances using `toEncoding`.++Other enhancements:++* A Cabal `fast` flag was added to disable building with optimizations. This drastically speeds up compiling both aeson ***and*** libraries using aeson so it is recommended to enable it during development. With cabal-install you can `cabal install aeson -ffast` and with stack you can add a flag section to your stack.yaml:+```+flags:+  aeson:+    fast: true+```++* Added list specific members to `ToJSON` and `FromJSON` classes. In+  the same way `Read` and `Show` handle lists specifically. This+  removes need for overlapping instances to handle `String`.++* Added a new `sumEncoding` option `UntaggedValue` which prevents+  objects from being tagged with the constructor name.++* JSONPaths are now tracked in instances derived with template-haskell+  and generics.++* Get rid of redundancy of JSONPath error messages in nested records.++  `eitherDecode "{\"x\":{\"a\": [1,2,true]}}" :: Either String Y`+  previously yielded+  `Error in $.x.a[2]: failed to parse field" x: failed to parse field a: expected Int, encountered Boolean`+  and now yields `Error in $.x.a[2]: expected Int, encountered Boolean"`.++  Some users might prefer to insert `modifyFailure` themselves to+  customize error messages, which previously prevented the use of+  `(.:)`.++* Backwards compatibility with `bytestring-0.9` using the+  `bytestring-builder` compatibility package.++* Export `decodeWith`, `decodeStrictWith`, `eitherDecodeWith`, and+  `eitherDecodeStrictWith` from `Data.Aeson.Parser`. This allows+  decoding using explicit parsers instead of using `FromJSON`+  instances.++* Un-orphan internal instances to render them in haddocks.++Other changes:++* Integral `FromJSON` instances now only accept integral+  values. E.g. parsing `3.14` to `Int` fails instead of succeeding+  with the value `3`.++* Over/underflows are now caught for bounded numeric types.++* Remove the `contents` field encoding with `allNullaryToStringTag = False`,+  giving us `{ "tag" : "c1" }` instead of `{ "tag" : "c1", contents : [] }`.+  The contents field is optional when parsing so this is only a breaking+  change for ToJSON instances.++* Fix a bug where `genericToEncoding` with `unwrapUnaryRecords = True`+  would produce an invalid encoding: `"unwrap\":""`.++* `ToJSON` instances using `genericToEncoding` and `omitNothingFields`+  no longer produce invalid JSON.++* Added instances for `DList`, `Compose`, `Product`, `Sum`.  ### 0.11.2.0 
examples/Generic.hs view
@@ -6,17 +6,19 @@ -- automatically derive the Generic class for us.  {-# LANGUAGE DeriveGeneric #-}- {-# LANGUAGE OverloadedStrings #-} +module Main (main) where++import Prelude ()+import Prelude.Compat+ import Data.Aeson (FromJSON, ToJSON, decode, encode) import qualified Data.ByteString.Lazy.Char8 as BL+import GHC.Generics (Generic)  -- To decode or encode a value using the generic machinery, we must -- make the type an instance of the Generic class.--import GHC.Generics (Generic)- data Coord = Coord { x :: Double, y :: Double }              deriving (Show, Generic) @@ -31,5 +33,5 @@ main = do   let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord   print req-  let reply = Coord 123.4 20+  let reply = Coord { x = 123.4, y = 20 }   BL.putStrLn (encode reply)
examples/Simplest.hs view
@@ -1,6 +1,12 @@-{-# LANGUAGE OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} -import Control.Applicative ((<$>), (<*>), empty)+module Main (main) where++import Prelude ()+import Prelude.Compat++import Control.Applicative (empty) import Data.Aeson import Data.Monoid import qualified Data.ByteString.Lazy.Char8 as BL
examples/TemplateHaskell.hs view
@@ -1,11 +1,14 @@ -- We can use Template Haskell (TH) to generate instances of the -- FromJSON and ToJSON classes automatically.  This is the fastest way -- to add JSON support for a type.-+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE OverloadedStrings #-}+module Main (main) where +import Prelude ()+import Prelude.Compat+ import Data.Aeson (decode, encode) import Data.Aeson.TH (deriveJSON, defaultOptions) import qualified Data.ByteString.Lazy.Char8 as BL@@ -21,5 +24,5 @@ main = do   let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord   print req-  let reply = Coord 123.4 20+  let reply = Coord { x = 123.4, y = 20 }   BL.putStrLn (encode reply)
examples/Twitter.hs view
@@ -8,22 +8,26 @@ -- renamed "type" to "type_" in the *.json files, to avoid overlap -- with a Haskell reserved keyword. -{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-} -module Twitter (+module Twitter+    (       Metadata(..)     , Geo(..)     , Story(..)     , Result(..)     ) where +import Prelude ()+import Prelude.Compat++import Control.DeepSeq import Data.Data (Typeable, Data) import Data.Int (Int64) import Data.Text (Text)--- import Data.Time (ZonedTime) import GHC.Generics (Generic) import Prelude hiding (id)-import Control.DeepSeq  data Metadata = Metadata {     result_type :: Text@@ -47,7 +51,7 @@   , metadata          :: Metadata   , to_user_id        :: Maybe Int64   , text              :: Text-  , id                :: Int64+  , id_               :: Int64   , from_user_id      :: Int64   , geo               :: Maybe Geo   , iso_language_code :: Text
examples/Twitter/Generic.hs view
@@ -1,5 +1,6 @@ -- Use GHC generics to automatically generate good instances.-+{-# LANGUAGE CPP #-}+{-# LANGUAGE PackageImports #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Twitter.Generic@@ -10,9 +11,18 @@     , Result(..)     ) where -import Data.Aeson (ToJSON, FromJSON)+import Prelude ()+import Prelude.Compat+ import Twitter +#ifndef HAS_BOTH_AESON_AND_BENCHMARKS+import Data.Aeson (ToJSON, FromJSON)+#else+import "aeson" Data.Aeson (ToJSON, FromJSON)+import qualified "aeson-benchmarks" Data.Aeson as B+#endif+ instance ToJSON Metadata instance FromJSON Metadata @@ -24,3 +34,17 @@  instance ToJSON Result instance FromJSON Result++#ifdef HAS_BOTH_AESON_AND_BENCHMARKS+instance B.ToJSON Metadata+instance B.FromJSON Metadata++instance B.ToJSON Geo+instance B.FromJSON Geo++instance B.ToJSON Story+instance B.FromJSON Story++instance B.ToJSON Result+instance B.FromJSON Result+#endif
examples/Twitter/Manual.hs view
@@ -1,6 +1,9 @@ -- Manually write instances. -{-# LANGUAGE OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE PackageImports #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  module Twitter.Manual@@ -11,13 +14,23 @@     , Result(..)     ) where +import Prelude ()+import Prelude.Compat+ import Control.Applicative-import Data.Aeson hiding (Result) import Data.Monoid ((<>)) import Prelude hiding (id) import Twitter +#ifndef HAS_BOTH_AESON_AND_BENCHMARKS+import Data.Aeson hiding (Result)+#else+import "aeson" Data.Aeson hiding (Result)+import qualified "aeson-benchmarks" Data.Aeson as B+#endif+ instance ToJSON Metadata where+   toJSON Metadata{..} = object [       "result_type" .= result_type     ]@@ -55,7 +68,7 @@     , "metadata"          .= metadata     , "to_user_id"        .= to_user_id     , "text"              .= text-    , "id"                .= id+    , "id"                .= id_     , "from_user_id"      .= from_user_id     , "geo"               .= geo     , "iso_language_code" .= iso_language_code@@ -72,7 +85,7 @@     <> "metadata"          .= metadata     <> "to_user_id"        .= to_user_id     <> "text"              .= text-    <> "id"                .= id+    <> "id"                .= id_     <> "from_user_id"      .= from_user_id     <> "geo"               .= geo     <> "iso_language_code" .= iso_language_code@@ -139,3 +152,128 @@     <*> v .: "max_id_str"     <*> v .: "query"   parseJSON _ = empty++#ifdef HAS_BOTH_AESON_AND_BENCHMARKS+instance B.ToJSON Metadata where+  toJSON Metadata{..} = B.object [+      "result_type" B..= result_type+    ]++  toEncoding Metadata{..} = B.pairs $+    "result_type" B..= result_type++instance B.FromJSON Metadata where+  parseJSON (B.Object v) = Metadata <$> v B..: "result_type"+  parseJSON _          = empty++instance B.ToJSON Geo where+  toJSON Geo{..} = B.object [+      "type_"       B..= type_+    , "coordinates" B..= coordinates+    ]++  toEncoding Geo{..} = B.pairs $+       "type_"       B..= type_+    <> "coordinates" B..= coordinates++instance B.FromJSON Geo where+  parseJSON (B.Object v) = Geo <$>+        v B..: "type_"+    <*> v B..: "coordinates"+  parseJSON _          = empty++instance B.ToJSON Story where+  toJSON Story{..} = B.object [+      "from_user_id_str"  B..= from_user_id_str+    , "profile_image_url" B..= profile_image_url+    , "created_at"        B..= created_at+    , "from_user"         B..= from_user+    , "id_str"            B..= id_str+    , "metadata"          B..= metadata+    , "to_user_id"        B..= to_user_id+    , "text"              B..= text+    , "id"                B..= id_+    , "from_user_id"      B..= from_user_id+    , "geo"               B..= geo+    , "iso_language_code" B..= iso_language_code+    , "to_user_id_str"    B..= to_user_id_str+    , "source"            B..= source+    ]++  toEncoding Story{..} = B.pairs $+       "from_user_id_str"  B..= from_user_id_str+    <> "profile_image_url" B..= profile_image_url+    <> "created_at"        B..= created_at+    <> "from_user"         B..= from_user+    <> "id_str"            B..= id_str+    <> "metadata"          B..= metadata+    <> "to_user_id"        B..= to_user_id+    <> "text"              B..= text+    <> "id"                B..= id_+    <> "from_user_id"      B..= from_user_id+    <> "geo"               B..= geo+    <> "iso_language_code" B..= iso_language_code+    <> "to_user_id_str"    B..= to_user_id_str+    <> "source"            B..= source++instance B.FromJSON Story where+  parseJSON (B.Object v) = Story <$>+        v B..: "from_user_id_str"+    <*> v B..: "profile_image_url"+    <*> v B..: "created_at"+    <*> v B..: "from_user"+    <*> v B..: "id_str"+    <*> v B..: "metadata"+    <*> v B..: "to_user_id"+    <*> v B..: "text"+    <*> v B..: "id"+    <*> v B..: "from_user_id"+    <*> v B..: "geo"+    <*> v B..: "iso_language_code"+    <*> v B..: "to_user_id_str"+    <*> v B..: "source"+  parseJSON _ = empty++instance B.ToJSON Result where+  toJSON Result{..} = B.object [+      "results"          B..= results+    , "max_id"           B..= max_id+    , "since_id"         B..= since_id+    , "refresh_url"      B..= refresh_url+    , "next_page"        B..= next_page+    , "results_per_page" B..= results_per_page+    , "page"             B..= page+    , "completed_in"     B..= completed_in+    , "since_id_str"     B..= since_id_str+    , "max_id_str"       B..= max_id_str+    , "query"            B..= query+    ]++  toEncoding Result{..} = B.pairs $+       "results"          B..= results+    <> "max_id"           B..= max_id+    <> "since_id"         B..= since_id+    <> "refresh_url"      B..= refresh_url+    <> "next_page"        B..= next_page+    <> "results_per_page" B..= results_per_page+    <> "page"             B..= page+    <> "completed_in"     B..= completed_in+    <> "since_id_str"     B..= since_id_str+    <> "max_id_str"       B..= max_id_str+    <> "query"            B..= query++instance B.FromJSON Result where+  parseJSON (B.Object v) = Result <$>+        v B..: "results"+    <*> v B..: "max_id"+    <*> v B..: "since_id"+    <*> v B..: "refresh_url"+    <*> v B..: "next_page"+    <*> v B..: "results_per_page"+    <*> v B..: "page"+    <*> v B..: "completed_in"+    <*> v B..: "since_id_str"+    <*> v B..: "max_id_str"+    <*> v B..: "query"+  parseJSON _ = empty+#endif
examples/Twitter/TH.hs view
@@ -1,5 +1,7 @@ -- Use Template Haskell to generate good instances. +{-# LANGUAGE CPP #-}+{-# LANGUAGE PackageImports #-} {-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -11,10 +13,25 @@     , Result(..)     ) where -import Data.Aeson.TH+import Prelude ()+ import Twitter +#ifndef HAS_BOTH_AESON_AND_BENCHMARKS+import Data.Aeson.TH+#else+import "aeson" Data.Aeson.TH+import qualified "aeson-benchmarks" Data.Aeson.TH as B+#endif+ $(deriveJSON defaultOptions ''Metadata) $(deriveJSON defaultOptions ''Geo) $(deriveJSON defaultOptions ''Story) $(deriveJSON defaultOptions ''Result)++#ifdef HAS_BOTH_AESON_AND_BENCHMARKS+$(B.deriveJSON B.defaultOptions ''Metadata)+$(B.deriveJSON B.defaultOptions ''Geo)+$(B.deriveJSON B.defaultOptions ''Story)+$(B.deriveJSON B.defaultOptions ''Result)+#endif
examples/aeson-examples.cabal view
@@ -9,6 +9,7 @@   build-depends:     aeson >= 0.10,     base,+    base-compat,     bytestring,     ghc-prim @@ -18,6 +19,7 @@   build-depends:     aeson,     base,+    base-compat,     bytestring  executable aeson-example-th@@ -26,4 +28,5 @@   build-depends:     aeson,     base,+    base-compat,     bytestring
include/overlapping-compat.h view
@@ -1,15 +1,8 @@ #if __GLASGOW_HASKELL__ >= 710 #define OVERLAPPABLE_ {-# OVERLAPPABLE #-} #define OVERLAPPING_  {-# OVERLAPPING #-}-#ifdef NEEDS_INCOHERENT-#define INCOHERENT_ {-# INCOHERENT #-}-#endif #else {-# LANGUAGE OverlappingInstances #-} #define OVERLAPPABLE_ #define OVERLAPPING_-#ifdef NEEDS_INCOHERENT-{-# LANGUAGE IncoherentInstances #-}-#define INCOHERENT_-#endif #endif
tests/DataFamilies/Encoders.hs view
@@ -1,12 +1,16 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TemplateHaskell #-}  module DataFamilies.Encoders where +import Prelude ()+import Prelude.Compat+ import Data.Aeson.TH import Data.Aeson.Types-import Options import DataFamilies.Types+import Options  -------------------------------------------------------------------------------- -- Nullary encoders/decoders@@ -136,3 +140,100 @@  thGADTParseJSONDefault :: Value -> Parser (GADT String) thGADTParseJSONDefault = $(mkParseJSON defaultOptions 'GADT)++--------------------------------------------------------------------------------+-- Generic encoders/decoders+--------------------------------------------------------------------------------++-- Nullary++gNullaryToJSONString :: Nullary Int -> Value+gNullaryToJSONString = genericToJSON defaultOptions++gNullaryToEncodingString :: Nullary Int -> Encoding+gNullaryToEncodingString = genericToEncoding defaultOptions++gNullaryParseJSONString :: Value -> Parser (Nullary Int)+gNullaryParseJSONString = genericParseJSON defaultOptions+++gNullaryToJSON2ElemArray :: Nullary Int -> Value+gNullaryToJSON2ElemArray = genericToJSON opts2ElemArray++gNullaryToEncoding2ElemArray :: Nullary Int -> Encoding+gNullaryToEncoding2ElemArray = genericToEncoding opts2ElemArray++gNullaryParseJSON2ElemArray :: Value -> Parser (Nullary Int)+gNullaryParseJSON2ElemArray = genericParseJSON opts2ElemArray+++gNullaryToJSONTaggedObject :: Nullary Int -> Value+gNullaryToJSONTaggedObject = genericToJSON optsTaggedObject++gNullaryToEncodingTaggedObject :: Nullary Int -> Encoding+gNullaryToEncodingTaggedObject = genericToEncoding optsTaggedObject++gNullaryParseJSONTaggedObject :: Value -> Parser (Nullary Int)+gNullaryParseJSONTaggedObject = genericParseJSON optsTaggedObject+++gNullaryToJSONObjectWithSingleField :: Nullary Int -> Value+gNullaryToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField++gNullaryToEncodingObjectWithSingleField :: Nullary Int -> Encoding+gNullaryToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingleField++gNullaryParseJSONObjectWithSingleField :: Value -> Parser (Nullary Int)+gNullaryParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField++-- SomeType++gSomeTypeToJSON2ElemArray :: SomeType c () Int -> Value+gSomeTypeToJSON2ElemArray = genericToJSON opts2ElemArray++gSomeTypeToEncoding2ElemArray :: SomeType c () Int -> Encoding+gSomeTypeToEncoding2ElemArray = genericToEncoding opts2ElemArray++gSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType c () Int)+gSomeTypeParseJSON2ElemArray = genericParseJSON opts2ElemArray+++gSomeTypeToJSONTaggedObject :: SomeType c () Int -> Value+gSomeTypeToJSONTaggedObject = genericToJSON optsTaggedObject++gSomeTypeToEncodingTaggedObject :: SomeType c () Int -> Encoding+gSomeTypeToEncodingTaggedObject = genericToEncoding optsTaggedObject++gSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType c () Int)+gSomeTypeParseJSONTaggedObject = genericParseJSON optsTaggedObject+++gSomeTypeToJSONObjectWithSingleField :: SomeType c () Int -> Value+gSomeTypeToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField++gSomeTypeToEncodingObjectWithSingleField :: SomeType c () Int -> Encoding+gSomeTypeToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingleField++gSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType c () Int)+gSomeTypeParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField++-- Approx++gApproxToJSONUnwrap :: Approx String -> Value+gApproxToJSONUnwrap = genericToJSON optsUnwrapUnaryRecords++gApproxToEncodingUnwrap :: Approx String -> Encoding+gApproxToEncodingUnwrap = genericToEncoding optsUnwrapUnaryRecords++gApproxParseJSONUnwrap :: Value -> Parser (Approx String)+gApproxParseJSONUnwrap = genericParseJSON optsUnwrapUnaryRecords+++gApproxToJSONDefault :: Approx String -> Value+gApproxToJSONDefault = genericToJSON defaultOptions++gApproxToEncodingDefault :: Approx String -> Encoding+gApproxToEncodingDefault = genericToEncoding defaultOptions++gApproxParseJSONDefault :: Value -> Parser (Approx String)+gApproxParseJSONDefault = genericParseJSON defaultOptions
tests/DataFamilies/Instances.hs view
@@ -4,14 +4,15 @@ {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -module DataFamilies.Instances where+module DataFamilies.Instances () where -import Control.Applicative+import Prelude ()+import Prelude.Compat+ import Data.Aeson.TH import Data.Aeson.Types (FromJSON(..)) import DataFamilies.Types import Test.QuickCheck (Arbitrary(..), elements, oneof)-import Prelude  instance (Arbitrary a) => Arbitrary (Approx a) where     arbitrary = Approx <$> arbitrary@@ -24,6 +25,7 @@                       , Unary   <$> arbitrary                       , Product <$> arbitrary <*> arbitrary <*> arbitrary                       , Record  <$> arbitrary <*> arbitrary <*> arbitrary+                      , List    <$> arbitrary                       ]  instance Arbitrary (GADT String) where
tests/DataFamilies/Properties.hs view
@@ -1,8 +1,12 @@+{-# LANGUAGE CPP #-}+ module DataFamilies.Properties (tests) where +import Prelude ()+import Prelude.Compat+ import DataFamilies.Encoders import DataFamilies.Instances ()- import Properties hiding (tests)  import Test.Framework (Test, testGroup)@@ -12,14 +16,13 @@  tests :: Test tests = testGroup "data families" [-  testGroup "template-haskell" [+    testGroup "template-haskell" [       testGroup "toJSON" [         testGroup "Nullary" [             testProperty "string" (isString . thNullaryToJSONString)           , testProperty "2ElemArray" (is2ElemArray . thNullaryToJSON2ElemArray)-          , testProperty "TaggedObject" (isTaggedObjectValue . thNullaryToJSONTaggedObject)+          , testProperty "TaggedObject" (isNullaryTaggedObject . thNullaryToJSONTaggedObject)           , testProperty "ObjectWithSingleField" (isObjectWithSingleField . thNullaryToJSONObjectWithSingleField)-           , testGroup "roundTrip" [               testProperty "string" (toParseJSON thNullaryParseJSONString thNullaryToJSONString)             , testProperty "2ElemArray" (toParseJSON thNullaryParseJSON2ElemArray thNullaryToJSON2ElemArray)@@ -36,21 +39,21 @@           , testProperty "TaggedObject" (toParseJSON thSomeTypeParseJSONTaggedObject thSomeTypeToJSONTaggedObject)           , testProperty "ObjectWithSingleField" (toParseJSON thSomeTypeParseJSONObjectWithSingleField thSomeTypeToJSONObjectWithSingleField)           ]+        ]       , testGroup "Approx" [-           testProperty "string"                (isString                . thApproxToJSONUnwrap)-         , testProperty "ObjectWithSingleField" (isObjectWithSingleField . thApproxToJSONDefault)-         , testGroup "roundTrip" [-               testProperty "string"                (toParseJSON thApproxParseJSONUnwrap  thApproxToJSONUnwrap)-             , testProperty "ObjectWithSingleField" (toParseJSON thApproxParseJSONDefault thApproxToJSONDefault)-           ]-         ]+          testProperty "string"                (isString                . thApproxToJSONUnwrap)+        , testProperty "ObjectWithSingleField" (isObjectWithSingleField . thApproxToJSONDefault)+        , testGroup "roundTrip" [+            testProperty "string"                (toParseJSON thApproxParseJSONUnwrap  thApproxToJSONUnwrap)+          , testProperty "ObjectWithSingleField" (toParseJSON thApproxParseJSONDefault thApproxToJSONDefault)+          ]+        ]       , testGroup "GADT" [           testProperty "string"                (isString                . thGADTToJSONUnwrap)         , testProperty "ObjectWithSingleField" (isObjectWithSingleField . thGADTToJSONDefault)         , testGroup "roundTrip" [-              testProperty "string"                (toParseJSON thGADTParseJSONUnwrap  thGADTToJSONUnwrap)-            , testProperty "ObjectWithSingleField" (toParseJSON thGADTParseJSONDefault thGADTToJSONDefault)-            ]+            testProperty "string"                (toParseJSON thGADTParseJSONUnwrap  thGADTToJSONUnwrap)+          , testProperty "ObjectWithSingleField" (toParseJSON thGADTParseJSONDefault thGADTToJSONDefault)           ]         ]       ]@@ -75,6 +78,63 @@       , testProperty "SomeTypeObjectWithSingleField" $         thSomeTypeToJSONObjectWithSingleField `sameAs`         thSomeTypeToEncodingObjectWithSingleField+      ]+    ]++  , testGroup "generics" [+      testGroup "toJSON" [+        testGroup "Nullary" [+            testProperty "string" (isString . gNullaryToJSONString)+          , testProperty "2ElemArray" (is2ElemArray . gNullaryToJSON2ElemArray)+          , testProperty "TaggedObject" (isNullaryTaggedObject . gNullaryToJSONTaggedObject)+          , testProperty "ObjectWithSingleField" (isObjectWithSingleField . gNullaryToJSONObjectWithSingleField)+          , testGroup "roundTrip" [+              testProperty "string" (toParseJSON gNullaryParseJSONString gNullaryToJSONString)+            , testProperty "2ElemArray" (toParseJSON gNullaryParseJSON2ElemArray gNullaryToJSON2ElemArray)+            , testProperty "TaggedObject" (toParseJSON gNullaryParseJSONTaggedObject gNullaryToJSONTaggedObject)+            , testProperty "ObjectWithSingleField" (toParseJSON gNullaryParseJSONObjectWithSingleField gNullaryToJSONObjectWithSingleField)+            ]+        ]+      , testGroup "SomeType" [+          testProperty "2ElemArray" (is2ElemArray . gSomeTypeToJSON2ElemArray)+        , testProperty "TaggedObject" (isTaggedObject . gSomeTypeToJSONTaggedObject)+        , testProperty "ObjectWithSingleField" (isObjectWithSingleField . gSomeTypeToJSONObjectWithSingleField)+        , testGroup "roundTrip" [+            testProperty "2ElemArray" (toParseJSON gSomeTypeParseJSON2ElemArray gSomeTypeToJSON2ElemArray)+          , testProperty "TaggedObject" (toParseJSON gSomeTypeParseJSONTaggedObject gSomeTypeToJSONTaggedObject)+          , testProperty "ObjectWithSingleField" (toParseJSON gSomeTypeParseJSONObjectWithSingleField gSomeTypeToJSONObjectWithSingleField)+          ]+        ]+      , testGroup "Approx" [+          testProperty "string"                (isString                . gApproxToJSONUnwrap)+        , testProperty "ObjectWithSingleField" (isObjectWithSingleField . gApproxToJSONDefault)+        , testGroup "roundTrip" [+            testProperty "string"                (toParseJSON gApproxParseJSONUnwrap  gApproxToJSONUnwrap)+          , testProperty "ObjectWithSingleField" (toParseJSON gApproxParseJSONDefault gApproxToJSONDefault)+          ]+        ]+      ]+    , testGroup "toEncoding" [+        testProperty "NullaryString" $+        gNullaryToJSONString `sameAs` gNullaryToEncodingString+      , testProperty "Nullary2ElemArray" $+        gNullaryToJSON2ElemArray `sameAs` gNullaryToEncoding2ElemArray+      , testProperty "NullaryTaggedObject" $+        gNullaryToJSONTaggedObject `sameAs` gNullaryToEncodingTaggedObject+      , testProperty "NullaryObjectWithSingleField" $+        gNullaryToJSONObjectWithSingleField `sameAs`+        gNullaryToEncodingObjectWithSingleField+      , testProperty "ApproxUnwrap" $+        gApproxToJSONUnwrap `sameAs` gApproxToEncodingUnwrap+      , testProperty "ApproxDefault" $+        gApproxToJSONDefault `sameAs` gApproxToEncodingDefault+      , testProperty "SomeType2ElemArray" $+        gSomeTypeToJSON2ElemArray `sameAs` gSomeTypeToEncoding2ElemArray+      , testProperty "SomeTypeTaggedObject" $+        gSomeTypeToJSONTaggedObject `sameAs` gSomeTypeToEncodingTaggedObject+      , testProperty "SomeTypeObjectWithSingleField" $+        gSomeTypeToJSONObjectWithSingleField `sameAs`+        gSomeTypeToEncodingObjectWithSingleField       ]     ]   ]
tests/DataFamilies/Types.hs view
@@ -1,11 +1,19 @@+-- DataKinds is needed for deriveAll0 calls on GHC 8+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}  module DataFamilies.Types where +import Prelude ()+import Prelude.Compat++import Generics.Deriving.TH (deriveAll0) import Types (ApproxEq(..))  data family Nullary a@@ -19,7 +27,9 @@                               | Record { testOne   :: Double                                        , testTwo   :: Maybe Bool                                        , testThree :: Maybe a-                                       } deriving (Eq, Show)+                                       }+                              | List [a]+    deriving (Eq, Show)  data family Approx a newtype instance Approx a = Approx { fromApprox :: a }@@ -34,3 +44,11 @@  deriving instance Eq   (GADT a) deriving instance Show (GADT a)++-- We use generic-deriving to be able to derive Generic instances for+-- data families on GHC 7.4.++$(deriveAll0 'C1)+$(deriveAll0 'C4)+$(deriveAll0 'Approx)+$(deriveAll0 'Nullary)
tests/Encoders.hs view
@@ -1,8 +1,12 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TemplateHaskell #-}  module Encoders where +import Prelude ()+import Prelude.Compat+ import Data.Aeson.TH import Data.Aeson.Types import Options@@ -56,6 +60,9 @@ gNullaryToJSONString :: Nullary -> Value gNullaryToJSONString = genericToJSON defaultOptions +gNullaryToEncodingString :: Nullary -> Encoding+gNullaryToEncodingString = genericToEncoding defaultOptions+ gNullaryParseJSONString :: Value -> Parser Nullary gNullaryParseJSONString = genericParseJSON defaultOptions @@ -63,6 +70,9 @@ gNullaryToJSON2ElemArray :: Nullary -> Value gNullaryToJSON2ElemArray = genericToJSON opts2ElemArray +gNullaryToEncoding2ElemArray :: Nullary -> Encoding+gNullaryToEncoding2ElemArray = genericToEncoding opts2ElemArray+ gNullaryParseJSON2ElemArray :: Value -> Parser Nullary gNullaryParseJSON2ElemArray = genericParseJSON opts2ElemArray @@ -70,6 +80,9 @@ gNullaryToJSONTaggedObject :: Nullary -> Value gNullaryToJSONTaggedObject = genericToJSON optsTaggedObject +gNullaryToEncodingTaggedObject :: Nullary -> Encoding+gNullaryToEncodingTaggedObject = genericToEncoding optsTaggedObject+ gNullaryParseJSONTaggedObject :: Value -> Parser Nullary gNullaryParseJSONTaggedObject = genericParseJSON optsTaggedObject @@ -77,6 +90,9 @@ gNullaryToJSONObjectWithSingleField :: Nullary -> Value gNullaryToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField +gNullaryToEncodingObjectWithSingleField :: Nullary -> Encoding+gNullaryToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingleField+ gNullaryParseJSONObjectWithSingleField :: Value -> Parser Nullary gNullaryParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField @@ -85,60 +101,163 @@ -- SomeType encoders/decoders -------------------------------------------------------------------------------- +-- Unary types+type LiftToJSON f a =+    (a -> Value) -> ([a] -> Value) -> f a -> Value+type LiftToEncoding f a =+    (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding+type LiftParseJSON f a =+    (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)+ thSomeTypeToJSON2ElemArray :: SomeType Int -> Value thSomeTypeToJSON2ElemArray = $(mkToJSON opts2ElemArray ''SomeType)  thSomeTypeToEncoding2ElemArray :: SomeType Int -> Encoding thSomeTypeToEncoding2ElemArray = $(mkToEncoding opts2ElemArray ''SomeType) +thSomeTypeLiftToJSON2ElemArray :: LiftToJSON SomeType a+thSomeTypeLiftToJSON2ElemArray = $(mkLiftToJSON opts2ElemArray ''SomeType)++thSomeTypeLiftToEncoding2ElemArray :: LiftToEncoding SomeType a+thSomeTypeLiftToEncoding2ElemArray = $(mkLiftToEncoding opts2ElemArray ''SomeType)+ thSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int) thSomeTypeParseJSON2ElemArray = $(mkParseJSON opts2ElemArray ''SomeType) +thSomeTypeLiftParseJSON2ElemArray :: LiftParseJSON SomeType a+thSomeTypeLiftParseJSON2ElemArray = $(mkLiftParseJSON opts2ElemArray ''SomeType) + thSomeTypeToJSONTaggedObject :: SomeType Int -> Value thSomeTypeToJSONTaggedObject = $(mkToJSON optsTaggedObject ''SomeType)  thSomeTypeToEncodingTaggedObject :: SomeType Int -> Encoding thSomeTypeToEncodingTaggedObject = $(mkToEncoding optsTaggedObject ''SomeType) +thSomeTypeLiftToJSONTaggedObject :: LiftToJSON SomeType a+thSomeTypeLiftToJSONTaggedObject = $(mkLiftToJSON optsTaggedObject ''SomeType)++thSomeTypeLiftToEncodingTaggedObject :: LiftToEncoding SomeType a+thSomeTypeLiftToEncodingTaggedObject = $(mkLiftToEncoding optsTaggedObject ''SomeType)+ thSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int) thSomeTypeParseJSONTaggedObject = $(mkParseJSON optsTaggedObject ''SomeType) +thSomeTypeLiftParseJSONTaggedObject :: LiftParseJSON SomeType a+thSomeTypeLiftParseJSONTaggedObject = $(mkLiftParseJSON optsTaggedObject ''SomeType) + thSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value-thSomeTypeToJSONObjectWithSingleField =-  $(mkToJSON optsObjectWithSingleField ''SomeType)+thSomeTypeToJSONObjectWithSingleField = $(mkToJSON optsObjectWithSingleField ''SomeType)  thSomeTypeToEncodingObjectWithSingleField :: SomeType Int -> Encoding-thSomeTypeToEncodingObjectWithSingleField =-  $(mkToEncoding optsObjectWithSingleField ''SomeType)+thSomeTypeToEncodingObjectWithSingleField = $(mkToEncoding optsObjectWithSingleField ''SomeType) +thSomeTypeLiftToJSONObjectWithSingleField :: LiftToJSON SomeType a+thSomeTypeLiftToJSONObjectWithSingleField = $(mkLiftToJSON optsObjectWithSingleField ''SomeType)++thSomeTypeLiftToEncodingObjectWithSingleField :: LiftToEncoding SomeType a+thSomeTypeLiftToEncodingObjectWithSingleField = $(mkLiftToEncoding optsObjectWithSingleField ''SomeType)+ thSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int)-thSomeTypeParseJSONObjectWithSingleField =-  $(mkParseJSON optsObjectWithSingleField ''SomeType)+thSomeTypeParseJSONObjectWithSingleField = $(mkParseJSON optsObjectWithSingleField ''SomeType) +thSomeTypeLiftParseJSONObjectWithSingleField :: LiftParseJSON SomeType a+thSomeTypeLiftParseJSONObjectWithSingleField = $(mkLiftParseJSON optsObjectWithSingleField ''SomeType) + gSomeTypeToJSON2ElemArray :: SomeType Int -> Value gSomeTypeToJSON2ElemArray = genericToJSON opts2ElemArray +gSomeTypeToEncoding2ElemArray :: SomeType Int -> Encoding+gSomeTypeToEncoding2ElemArray = genericToEncoding opts2ElemArray+ gSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int) gSomeTypeParseJSON2ElemArray = genericParseJSON opts2ElemArray +#if __GLASGOW_HASKELL__ >= 706+gSomeTypeLiftToEncoding2ElemArray :: LiftToEncoding SomeType a+gSomeTypeLiftToEncoding2ElemArray = genericLiftToEncoding opts2ElemArray +gSomeTypeLiftToJSON2ElemArray :: LiftToJSON SomeType a+gSomeTypeLiftToJSON2ElemArray = genericLiftToJSON opts2ElemArray++gSomeTypeLiftParseJSON2ElemArray :: LiftParseJSON SomeType a+gSomeTypeLiftParseJSON2ElemArray = genericLiftParseJSON opts2ElemArray+#endif++ gSomeTypeToJSONTaggedObject :: SomeType Int -> Value gSomeTypeToJSONTaggedObject = genericToJSON optsTaggedObject +gSomeTypeToEncodingTaggedObject :: SomeType Int -> Encoding+gSomeTypeToEncodingTaggedObject = genericToEncoding optsTaggedObject+ gSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int) gSomeTypeParseJSONTaggedObject = genericParseJSON optsTaggedObject +#if __GLASGOW_HASKELL__ >= 706+gSomeTypeLiftToEncodingTaggedObject :: LiftToEncoding SomeType a+gSomeTypeLiftToEncodingTaggedObject = genericLiftToEncoding optsTaggedObject +gSomeTypeLiftToJSONTaggedObject :: LiftToJSON SomeType a+gSomeTypeLiftToJSONTaggedObject = genericLiftToJSON optsTaggedObject++gSomeTypeLiftParseJSONTaggedObject :: LiftParseJSON SomeType a+gSomeTypeLiftParseJSONTaggedObject = genericLiftParseJSON optsTaggedObject+#endif++ gSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value gSomeTypeToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField +gSomeTypeToEncodingObjectWithSingleField :: SomeType Int -> Encoding+gSomeTypeToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingleField+ gSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int) gSomeTypeParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField +#if __GLASGOW_HASKELL__ >= 706+gSomeTypeLiftToEncodingObjectWithSingleField :: LiftToEncoding SomeType a+gSomeTypeLiftToEncodingObjectWithSingleField = genericLiftToEncoding optsObjectWithSingleField +gSomeTypeLiftToJSONObjectWithSingleField :: LiftToJSON SomeType a+gSomeTypeLiftToJSONObjectWithSingleField = genericLiftToJSON optsObjectWithSingleField++gSomeTypeLiftParseJSONObjectWithSingleField :: LiftParseJSON SomeType a+gSomeTypeLiftParseJSONObjectWithSingleField = genericLiftParseJSON optsObjectWithSingleField+#endif+++gSomeTypeToJSONOmitNothingFields :: SomeType Int -> Value+gSomeTypeToJSONOmitNothingFields = genericToJSON optsOmitNothingFields++gSomeTypeToEncodingOmitNothingFields :: SomeType Int -> Encoding+gSomeTypeToEncodingOmitNothingFields = genericToEncoding optsOmitNothingFields++-------------------------------------------------------------------------------+-- EitherTextInt encoders/decodes+-------------------------------------------------------------------------------++thEitherTextIntToJSONUntaggedValue :: EitherTextInt -> Value+thEitherTextIntToJSONUntaggedValue = $(mkToJSON optsUntaggedValue ''EitherTextInt)++thEitherTextIntToEncodingUntaggedValue :: EitherTextInt -> Encoding+thEitherTextIntToEncodingUntaggedValue = $(mkToEncoding optsUntaggedValue ''EitherTextInt)++thEitherTextIntParseJSONUntaggedValue :: Value -> Parser EitherTextInt+thEitherTextIntParseJSONUntaggedValue = $(mkParseJSON optsUntaggedValue ''EitherTextInt)+++gEitherTextIntToJSONUntaggedValue :: EitherTextInt -> Value+gEitherTextIntToJSONUntaggedValue = genericToJSON optsUntaggedValue++gEitherTextIntToEncodingUntaggedValue :: EitherTextInt -> Encoding+gEitherTextIntToEncodingUntaggedValue = genericToEncoding optsUntaggedValue++gEitherTextIntParseJSONUntaggedValue :: Value -> Parser EitherTextInt+gEitherTextIntParseJSONUntaggedValue = genericParseJSON optsUntaggedValue+ -------------------------------------------------------------------------------- -- Approx encoders/decoders --------------------------------------------------------------------------------@@ -165,12 +284,18 @@ gApproxToJSONUnwrap :: Approx String -> Value gApproxToJSONUnwrap = genericToJSON optsUnwrapUnaryRecords +gApproxToEncodingUnwrap :: Approx String -> Encoding+gApproxToEncodingUnwrap = genericToEncoding optsUnwrapUnaryRecords+ gApproxParseJSONUnwrap :: Value -> Parser (Approx String) gApproxParseJSONUnwrap = genericParseJSON optsUnwrapUnaryRecords   gApproxToJSONDefault :: Approx String -> Value gApproxToJSONDefault = genericToJSON defaultOptions++gApproxToEncodingDefault :: Approx String -> Encoding+gApproxToEncodingDefault = genericToEncoding defaultOptions  gApproxParseJSONDefault :: Value -> Parser (Approx String) gApproxParseJSONDefault = genericParseJSON defaultOptions
tests/Functions.hs view
@@ -1,4 +1,11 @@-module Functions where+module Functions+    (+      approxEq+    , approxEqWith+    ) where++import Prelude ()+import Prelude.Compat  approxEq :: (Fractional a, Ord a) => a -> a -> Bool approxEq = approxEqWith 1e-15 1e-15
tests/Instances.hs view
@@ -1,30 +1,39 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -module Instances where+module Instances () where -import Types-import Data.Function (on)+import Prelude ()+import Prelude.Compat++import Control.Applicative (Const(..), empty) import Control.Monad-import Test.QuickCheck (Arbitrary(..), getNonNegative, elements,-                        listOf1, oneof, resize)-import Data.Time.Clock (UTCTime(..))-import Data.Time (ZonedTime(..), TimeZone(..))-import Data.List.NonEmpty (NonEmpty(..))-import Data.Version import Data.Aeson.Types-import Control.Applicative (Const(..))-import Data.Tagged (Tagged(..))+import Data.Function (on)+import Data.Functor.Compose (Compose (..))+import Data.Functor.Identity (Identity (..))+import Data.List.NonEmpty (NonEmpty(..)) import Data.Proxy (Proxy(..))-import Control.Applicative+import Data.Tagged (Tagged(..))+import Data.Time (ZonedTime(..), TimeZone(..))+import Data.Time.Clock (UTCTime(..))+import Data.Version import Functions+import Test.QuickCheck (Arbitrary(..), getNonNegative, elements, listOf1, oneof, resize)+import Types+import qualified Data.DList as DList+import qualified Data.HashMap.Strict as HM  import Data.Orphans () import Test.QuickCheck.Instances ()+#if MIN_VERSION_base(4,7,0)+import Data.Hashable.Time ()+#endif  #if !MIN_VERSION_base(4,8,0) && !MIN_VERSION_QuickCheck(2,8,3) import Numeric.Natural@@ -51,9 +60,21 @@ instance ApproxEq DotNetTime where     (=~) = (=~) `on` fromDotNetTime +instance ApproxEq Float where+    a =~ b+      | isNaN a && isNaN b = True+      | otherwise          = approxEq a b+ instance ApproxEq Double where-    (=~) = approxEq+    a =~ b+      | isNaN a && isNaN b = True+      | otherwise          = approxEq a b +instance (ApproxEq k, Eq v) => ApproxEq (HM.HashMap k v) where+    a =~ b = and $ zipWith eq (HM.toList a) (HM.toList b)+      where+        eq (x,y) (u,v) = x =~ u && y == v+ -- Test-related types.  instance Arbitrary Foo where@@ -131,8 +152,17 @@                       , Unary   <$> arbitrary                       , Product <$> arbitrary <*> arbitrary <*> arbitrary                       , Record  <$> arbitrary <*> arbitrary <*> arbitrary+                      , List    <$> arbitrary                       ] +instance Arbitrary EitherTextInt where+    arbitrary = oneof+        [ LeftBool <$> arbitrary+        , RightInt <$> arbitrary+        , BothTextInt <$> arbitrary <*> arbitrary+        , pure NoneNullary+        ]+ instance Arbitrary (GADT String) where     arbitrary = GADT <$> arbitrary @@ -142,17 +172,12 @@ instance (ApproxEq a) => ApproxEq [a] where     a =~ b = length a == length b && all (uncurry (=~)) (zip a b) -#if !MIN_VERSION_QuickCheck(2,9,0) instance Arbitrary Version where     arbitrary = makeVersion . fmap getNonNegative <$> resize 4 (listOf1 arbitrary)  instance Arbitrary a => Arbitrary (NonEmpty a) where     arbitrary = (:|) <$> arbitrary <*> arbitrary -instance Arbitrary a => Arbitrary (Const a b) where-    arbitrary = Const <$> arbitrary-#endif- -- Version tags are deprecated, so we avoid using them in the Arbitrary -- instance. However, the recommended constructor 'makeVersion' is not -- exported by "Data.Version" until base-4.8.0.0. For previous versions,@@ -173,3 +198,16 @@  instance Arbitrary b => Arbitrary (Tagged a b) where     arbitrary = Tagged <$> arbitrary++instance Arbitrary a => Arbitrary (Const a b) where+    arbitrary = Const <$> arbitrary++instance Arbitrary a => Arbitrary (DList.DList a) where+    arbitrary = DList.fromList <$> arbitrary++-- would like to have -- https://github.com/nick8325/quickcheck/issues/73+instance Arbitrary a => Arbitrary (Identity a) where+    arbitrary = Identity <$> arbitrary++instance Arbitrary (f (g a)) => Arbitrary (Compose f g a) where+    arbitrary = Compose <$> arbitrary
tests/Options.hs view
@@ -1,5 +1,8 @@ module Options where +import Prelude ()+import Prelude.Compat+ import Data.Aeson.Types import Data.Char @@ -29,3 +32,13 @@                             { allNullaryToStringTag = False                             , sumEncoding           = ObjectWithSingleField                             }++optsOmitNothingFields :: Options+optsOmitNothingFields = optsDefault+                        { omitNothingFields = True+                        }++optsUntaggedValue :: Options+optsUntaggedValue = optsDefault+    { sumEncoding = UntaggedValue+    }
tests/Properties.hs view
@@ -1,20 +1,32 @@-{-# LANGUAGE OverloadedStrings, RecordWildCards, ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} -- For arbitrary Compose+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Properties where +import Prelude ()+import Prelude.Compat+ import Control.Applicative (Const)-import Data.Aeson (eitherDecode)-import Data.Aeson.Encode (encode)+import Data.Aeson (eitherDecode, encode)+import Data.Aeson.Encoding (encodingToLazyByteString) import Data.Aeson.Internal (IResult(..), formatError, ifromJSON, iparse) import Data.Aeson.Parser (value) import Data.Aeson.Types-import Data.ByteString.Builder (toLazyByteString)+import Data.DList (DList)+import Data.Functor.Compose (Compose (..))+import Data.HashMap.Strict (HashMap)+import Data.Hashable (Hashable) import Data.Int (Int8) import Data.List.NonEmpty (NonEmpty)-import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay, UTCTime,-                  ZonedTime)+import Data.Map (Map) import Data.Proxy (Proxy)+import Data.Ratio (Ratio)+import Data.Sequence (Seq) import Data.Tagged (Tagged)+import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime) import Data.Version (Version) import Encoders import Instances ()@@ -28,6 +40,7 @@ import qualified Data.HashMap.Strict as H import qualified Data.Map as Map import qualified Data.Text as T+import qualified Data.Text.Lazy as LT import qualified Data.Vector as V  encodeDouble :: Double -> Double -> Property@@ -39,13 +52,24 @@ encodeInteger :: Integer -> Property encodeInteger i = encode i === L.pack (show i) -toParseJSON :: (Arbitrary a, Eq a, Show a) =>+toParseJSON :: (Eq a, Show a) =>                (Value -> Parser a) -> (a -> Value) -> a -> Property toParseJSON parsejson tojson x =     case iparse parsejson . tojson $ x of       IError path msg -> failure "parse" (formatError path msg) x       ISuccess x'     -> x === x' +toParseJSON1+    :: (Eq (f Int), Show (f Int))+    => (forall a. LiftParseJSON f a)+    -> (forall a. LiftToJSON f a)+    -> f Int+    -> Property+toParseJSON1 parsejson1 tojson1 = toParseJSON parsejson tojson+  where+    parsejson = parsejson1 parseJSON (listParser parseJSON)+    tojson    = tojson1 toJSON (listValue toJSON)+ roundTripEnc :: (FromJSON a, ToJSON a, Show a) =>              (a -> a -> Property) -> a -> a -> Property roundTripEnc eq _ i =@@ -64,14 +88,17 @@ roundTripEq :: (Eq a, FromJSON a, ToJSON a, Show a) => a -> a -> Property roundTripEq x y = roundTripEnc (===) x y .&&. roundTripNoEnc (===) x y +-- We test keys by encoding HashMap and Map with it+roundTripKey+    :: (Ord a, Hashable a, FromJSONKey a, ToJSONKey a, Show a)+    => a -> HashMap a Int -> Map a Int -> Property+roundTripKey _ h m = roundTripEq h h .&&. roundTripEq m m+ infix 4 ==~ (==~) :: (ApproxEq a, Show a) => a -> a -> Property x ==~ y =   counterexample (show x ++ " /= " ++ show y) (x =~ y) -roundTripApproxEq :: (ApproxEq a, FromJSON a, ToJSON a, Show a) => a -> a -> Property-roundTripApproxEq x y = roundTripEnc (==~) x y .&&. roundTripNoEnc (==~) x y- toFromJSON :: (Arbitrary a, Eq a, FromJSON a, ToJSON a, Show a) => a -> Property toFromJSON x = case ifromJSON (toJSON x) of                 IError path err -> failure "fromJSON" (formatError path err) x@@ -90,8 +117,30 @@ -- variation in JSON object key ordering. sameAs :: (a -> Value) -> (a -> Encoding) -> a -> Property sameAs toVal toEnc v =-  eitherDecode (toLazyByteString (fromEncoding (toEnc v))) === Right (toVal v)+  eitherDecode (encodingToLazyByteString (toEnc v)) === Right (toVal v) +sameAs1+    :: (forall a. LiftToJSON f a)+    -> (forall a. LiftToEncoding f a)+    -> f Int+    -> Property+sameAs1 toVal1 toEnc1 v = lhs === rhs+  where+    rhs = Right $ toVal1 toJSON (listValue toJSON) v+    lhs = eitherDecode . encodingToLazyByteString $+        toEnc1 toEncoding (listEncoding toEncoding) v++sameAs1Agree+    :: ToJSON a+    => (f a -> Encoding)+    -> (forall b. LiftToEncoding f b)+    -> f a+    -> Property+sameAs1Agree toEnc toEnc1 v = rhs === lhs+  where+    rhs = encodingToLazyByteString $ toEnc v+    lhs = encodingToLazyByteString $ toEnc1 toEncoding (listEncoding toEncoding) v+ type P6 = Product6 Int Bool String (Approx Double) (Int, Approx Double) () type S4 = Sum4 Int8 ZonedTime T.Text (Map.Map String Int) @@ -112,6 +161,9 @@                                    "contents" `H.member` obj isTaggedObjectValue _            = False +isNullaryTaggedObject :: Value -> Bool+isNullaryTaggedObject obj = isTaggedObject obj && isObjectWithSingleField obj+ isTaggedObject :: Value -> Bool isTaggedObject (Object obj) = "tag" `H.member` obj isTaggedObject _            = False@@ -120,8 +172,19 @@ isObjectWithSingleField (Object obj) = H.size obj == 1 isObjectWithSingleField _            = False +-- | is untaggedValue of EitherTextInt+isUntaggedValueETI :: Value -> Bool+isUntaggedValueETI (String s)+    | s == "nonenullary"   = True+isUntaggedValueETI (Bool _)   = True+isUntaggedValueETI (Number _) = True+isUntaggedValueETI (Array a)  = length a == 2+isUntaggedValueETI _          = False++ -------------------------------------------------------------------------------- + tests :: Test tests = testGroup "properties" [   testGroup "encode" [@@ -136,9 +199,10 @@     , testProperty "Integer" $ roundTripEq (1 :: Integer)     , testProperty "String" $ roundTripEq ("" :: String)     , testProperty "Text" $ roundTripEq T.empty+    , testProperty "Lazy Text" $ roundTripEq LT.empty     , testProperty "Foo" $ roundTripEq (undefined :: Foo)     , testProperty "Day" $ roundTripEq (undefined :: Day)-    , testProperty "DotNetTime" $ roundTripApproxEq (undefined :: DotNetTime)+    , testProperty "DotNetTime" $ roundTripEq (undefined :: Approx DotNetTime)     , testProperty "LocalTime" $ roundTripEq (undefined :: LocalTime)     , testProperty "TimeOfDay" $ roundTripEq (undefined :: TimeOfDay)     , testProperty "UTCTime" $ roundTripEq (undefined :: UTCTime)@@ -149,6 +213,45 @@     , testProperty "Proxy" $ roundTripEq (undefined :: Proxy Int)     , testProperty "Tagged" $ roundTripEq (undefined :: Tagged Int Char)     , testProperty "Const" $ roundTripEq (undefined :: Const Int Char)+    , testProperty "DList" $ roundTripEq (undefined :: DList Int)+    , testProperty "Seq" $ roundTripEq (undefined :: Seq Int)+    , testProperty "Rational" $ roundTripEq (undefined :: Rational)+    , testProperty "Ratio Int" $ roundTripEq (undefined :: Ratio Int)+    , testGroup "functors"+      [ testProperty "Identity Char" $ roundTripEq (undefined :: I Int)++      , testProperty "Identity Char" $ roundTripEq (undefined :: I Char)+      , testProperty "Identity [Char]" $ roundTripEq (undefined :: I [Char])+      , testProperty "[Identity Char]" $ roundTripEq (undefined :: [I Char])++      , testProperty "Compose I  I  Int" $ roundTripEq (undefined :: Compose I  I  Int)+      , testProperty "Compose [] I  Int" $ roundTripEq (undefined :: Compose [] I  Int)+      , testProperty "Compose I  [] Int" $ roundTripEq (undefined :: Compose I  [] Int)+      , testProperty "Compose [] [] Int" $ roundTripEq (undefined :: Compose [] [] Int)++      , testProperty "Compose I  I  Char" $ roundTripEq (undefined :: Compose I  I  Char)+      , testProperty "Compose [] I  Char" $ roundTripEq (undefined :: Compose [] I  Char)+      , testProperty "Compose I  [] Char" $ roundTripEq (undefined :: Compose I  [] Char)+      , testProperty "Compose [] [] Char" $ roundTripEq (undefined :: Compose [] [] Char)++      , testProperty "Compose3 I  I  I  Char" $ roundTripEq (undefined :: Compose3 I  I  I  Char)+      , testProperty "Compose3 I  [] I  Char" $ roundTripEq (undefined :: Compose3 I  [] I  Char)+      , testProperty "Compose3 I  I  [] Char" $ roundTripEq (undefined :: Compose3 I  I  [] Char)+      , testProperty "Compose3 I  [] [] Char" $ roundTripEq (undefined :: Compose3 I  [] [] Char)+      , testProperty "Compose3 [] I  I  Char" $ roundTripEq (undefined :: Compose3 [] I  I  Char)+      , testProperty "Compose3 [] [] I  Char" $ roundTripEq (undefined :: Compose3 [] [] I  Char)+      , testProperty "Compose3 [] I  [] Char" $ roundTripEq (undefined :: Compose3 [] I  [] Char)+      , testProperty "Compose3 [] [] [] Char" $ roundTripEq (undefined :: Compose3 [] [] [] Char)++      , testProperty "Compose3' I  I  I  Char" $ roundTripEq (undefined :: Compose3' I  I  I  Char)+      , testProperty "Compose3' I  [] I  Char" $ roundTripEq (undefined :: Compose3' I  [] I  Char)+      , testProperty "Compose3' I  I  [] Char" $ roundTripEq (undefined :: Compose3' I  I  [] Char)+      , testProperty "Compose3' I  [] [] Char" $ roundTripEq (undefined :: Compose3' I  [] [] Char)+      , testProperty "Compose3' [] I  I  Char" $ roundTripEq (undefined :: Compose3' [] I  I  Char)+      , testProperty "Compose3' [] [] I  Char" $ roundTripEq (undefined :: Compose3' [] [] I  Char)+      , testProperty "Compose3' [] I  [] Char" $ roundTripEq (undefined :: Compose3' [] I  [] Char)+      , testProperty "Compose3' [] [] [] Char" $ roundTripEq (undefined :: Compose3' [] [] [] Char)+      ]     , testGroup "ghcGenerics" [         testProperty "OneConstructor" $ roundTripEq OneConstructor       , testProperty "Product2" $ roundTripEq (undefined :: Product2 Int Bool)@@ -156,6 +259,26 @@       , testProperty "Sum4" $ roundTripEq (undefined :: S4)       ]     ]+  , testGroup "roundTrip Key"+    [ testProperty "Bool" $ roundTripKey True+    , testProperty "Text" $ roundTripKey (undefined :: T.Text)+    , testProperty "String" $ roundTripKey (undefined :: String)+    , testProperty "Int" $ roundTripKey (undefined :: Int)+    , testProperty "[Text]" $ roundTripKey (undefined :: [T.Text])+    , testProperty "(Int,Char)" $ roundTripKey (undefined :: (Int,Char))+    , testProperty "Integer" $ roundTripKey (undefined :: Integer)+    , testProperty "Natural" $ roundTripKey (undefined :: Natural)+    , testProperty "Float" $ roundTripKey (undefined :: Float)+    , testProperty "Double" $ roundTripKey (undefined :: Double)+#if MIN_VERSION_base(4,7,0)+    , testProperty "Day" $ roundTripKey (undefined :: Day)+    , testProperty "LocalTime" $ roundTripKey (undefined :: LocalTime)+    , testProperty "TimeOfDay" $ roundTripKey (undefined :: TimeOfDay)+    , testProperty "UTCTime" $ roundTripKey (undefined :: UTCTime)+#endif+    , testProperty "Version" $ roundTripKey (undefined :: Version)+    , testProperty "Lazy Text" $ roundTripKey (undefined :: LT.Text)+    ]   , testGroup "toFromJSON" [       testProperty "Integer" (toFromJSON :: Integer -> Property)     , testProperty "Double" (toFromJSON :: Double -> Property)@@ -166,12 +289,96 @@   , testGroup "failure messages" [       testProperty "modify failure" modifyFailureProp     ]+  , testGroup "generic" [+      testGroup "toJSON" [+        testGroup "Nullary" [+            testProperty "string" (isString . gNullaryToJSONString)+          , testProperty "2ElemArray" (is2ElemArray . gNullaryToJSON2ElemArray)+          , testProperty "TaggedObject" (isNullaryTaggedObject . gNullaryToJSONTaggedObject)+          , testProperty "ObjectWithSingleField" (isObjectWithSingleField . gNullaryToJSONObjectWithSingleField)+          , testGroup "roundTrip" [+              testProperty "string" (toParseJSON gNullaryParseJSONString gNullaryToJSONString)+            , testProperty "2ElemArray" (toParseJSON gNullaryParseJSON2ElemArray gNullaryToJSON2ElemArray)+            , testProperty "TaggedObject" (toParseJSON gNullaryParseJSONTaggedObject gNullaryToJSONTaggedObject)+            , testProperty "ObjectWithSingleField" (toParseJSON gNullaryParseJSONObjectWithSingleField gNullaryToJSONObjectWithSingleField)+            ]+        ]+      , testGroup "EitherTextInt" [+          testProperty "UntaggedValue" (isUntaggedValueETI . gEitherTextIntToJSONUntaggedValue)+        , testProperty "roundtrip" (toParseJSON gEitherTextIntParseJSONUntaggedValue gEitherTextIntToJSONUntaggedValue)+        ]+      , testGroup "SomeType" [+          testProperty "2ElemArray" (is2ElemArray . gSomeTypeToJSON2ElemArray)+        , testProperty "TaggedObject" (isTaggedObject . gSomeTypeToJSONTaggedObject)+        , testProperty "ObjectWithSingleField" (isObjectWithSingleField . gSomeTypeToJSONObjectWithSingleField)+        , testGroup "roundTrip" [+            testProperty "2ElemArray" (toParseJSON gSomeTypeParseJSON2ElemArray gSomeTypeToJSON2ElemArray)+          , testProperty "TaggedObject" (toParseJSON gSomeTypeParseJSONTaggedObject gSomeTypeToJSONTaggedObject)+          , testProperty "ObjectWithSingleField" (toParseJSON gSomeTypeParseJSONObjectWithSingleField gSomeTypeToJSONObjectWithSingleField)++#if __GLASGOW_HASKELL__ >= 706+          , testProperty "2ElemArray unary" (toParseJSON1 gSomeTypeLiftParseJSON2ElemArray gSomeTypeLiftToJSON2ElemArray)+          , testProperty "TaggedObject unary" (toParseJSON1 gSomeTypeLiftParseJSONTaggedObject gSomeTypeLiftToJSONTaggedObject)+          , testProperty "ObjectWithSingleField unary" (toParseJSON1 gSomeTypeLiftParseJSONObjectWithSingleField gSomeTypeLiftToJSONObjectWithSingleField)+#endif+          ]+        ]+      ]+    , testGroup "toEncoding" [+        testProperty "NullaryString" $+        gNullaryToJSONString `sameAs` gNullaryToEncodingString+      , testProperty "Nullary2ElemArray" $+        gNullaryToJSON2ElemArray `sameAs` gNullaryToEncoding2ElemArray+      , testProperty "NullaryTaggedObject" $+        gNullaryToJSONTaggedObject `sameAs` gNullaryToEncodingTaggedObject+      , testProperty "NullaryObjectWithSingleField" $+        gNullaryToJSONObjectWithSingleField `sameAs`+        gNullaryToEncodingObjectWithSingleField+      -- , testProperty "ApproxUnwrap" $+      --   gApproxToJSONUnwrap `sameAs` gApproxToEncodingUnwrap+      , testProperty "ApproxDefault" $+        gApproxToJSONDefault `sameAs` gApproxToEncodingDefault++      , testProperty "EitherTextInt UntaggedValue" $+        gEitherTextIntToJSONUntaggedValue `sameAs` gEitherTextIntToEncodingUntaggedValue++      , testProperty "SomeType2ElemArray" $+        gSomeTypeToJSON2ElemArray `sameAs` gSomeTypeToEncoding2ElemArray+#if __GLASGOW_HASKELL__ >= 706+      , testProperty "SomeType2ElemArray unary" $+        gSomeTypeLiftToJSON2ElemArray `sameAs1` gSomeTypeLiftToEncoding2ElemArray+      , testProperty "SomeType2ElemArray unary agree" $+        gSomeTypeToEncoding2ElemArray `sameAs1Agree` gSomeTypeLiftToEncoding2ElemArray+#endif++      , testProperty "SomeTypeTaggedObject" $+        gSomeTypeToJSONTaggedObject `sameAs` gSomeTypeToEncodingTaggedObject+#if __GLASGOW_HASKELL__ >= 706+      , testProperty "SomeTypeTaggedObject unary" $+        gSomeTypeLiftToJSONTaggedObject `sameAs1` gSomeTypeLiftToEncodingTaggedObject+      , testProperty "SomeTypeTaggedObject unary agree" $+        gSomeTypeToEncodingTaggedObject `sameAs1Agree` gSomeTypeLiftToEncodingTaggedObject+#endif++      , testProperty "SomeTypeObjectWithSingleField" $+        gSomeTypeToJSONObjectWithSingleField `sameAs` gSomeTypeToEncodingObjectWithSingleField+#if __GLASGOW_HASKELL__ >= 706+      , testProperty "SomeTypeObjectWithSingleField unary" $+        gSomeTypeLiftToJSONObjectWithSingleField `sameAs1` gSomeTypeLiftToEncodingObjectWithSingleField+      , testProperty "SomeTypeObjectWithSingleField unary agree" $+        gSomeTypeToEncodingObjectWithSingleField `sameAs1Agree` gSomeTypeLiftToEncodingObjectWithSingleField+#endif++      , testProperty "SomeTypeOmitNothingFields" $+        gSomeTypeToJSONOmitNothingFields `sameAs` gSomeTypeToEncodingOmitNothingFields+      ]+    ]   , testGroup "template-haskell" [       testGroup "toJSON" [         testGroup "Nullary" [             testProperty "string" (isString . thNullaryToJSONString)           , testProperty "2ElemArray" (is2ElemArray . thNullaryToJSON2ElemArray)-          , testProperty "TaggedObject" (isTaggedObjectValue . thNullaryToJSONTaggedObject)+          , testProperty "TaggedObject" (isNullaryTaggedObject . thNullaryToJSONTaggedObject)           , testProperty "ObjectWithSingleField" (isObjectWithSingleField . thNullaryToJSONObjectWithSingleField)            , testGroup "roundTrip" [@@ -181,6 +388,10 @@             , testProperty "ObjectWithSingleField" (toParseJSON thNullaryParseJSONObjectWithSingleField thNullaryToJSONObjectWithSingleField)             ]         ]+      , testGroup "EitherTextInt" [+          testProperty "UntaggedValue" (isUntaggedValueETI . thEitherTextIntToJSONUntaggedValue)+        , testProperty "roundtrip" (toParseJSON thEitherTextIntParseJSONUntaggedValue thEitherTextIntToJSONUntaggedValue)+        ]       , testGroup "SomeType" [           testProperty "2ElemArray" (is2ElemArray . thSomeTypeToJSON2ElemArray)         , testProperty "TaggedObject" (isTaggedObject . thSomeTypeToJSONTaggedObject)@@ -189,6 +400,11 @@             testProperty "2ElemArray" (toParseJSON thSomeTypeParseJSON2ElemArray thSomeTypeToJSON2ElemArray)           , testProperty "TaggedObject" (toParseJSON thSomeTypeParseJSONTaggedObject thSomeTypeToJSONTaggedObject)           , testProperty "ObjectWithSingleField" (toParseJSON thSomeTypeParseJSONObjectWithSingleField thSomeTypeToJSONObjectWithSingleField)++          , testProperty "2ElemArray unary" (toParseJSON1 thSomeTypeLiftParseJSON2ElemArray thSomeTypeLiftToJSON2ElemArray)+          , testProperty "TaggedObject unary" (toParseJSON1 thSomeTypeLiftParseJSONTaggedObject thSomeTypeLiftToJSONTaggedObject)+          , testProperty "ObjectWithSingleField unary" (toParseJSON1 thSomeTypeLiftParseJSONObjectWithSingleField thSomeTypeLiftToJSONObjectWithSingleField)+           ]        , testGroup "Approx" [             testProperty "string"                (isString                . thApproxToJSONUnwrap)@@ -222,13 +438,30 @@         thApproxToJSONUnwrap `sameAs` thApproxToEncodingUnwrap       , testProperty "ApproxDefault" $         thApproxToJSONDefault `sameAs` thApproxToEncodingDefault++      , testProperty "EitherTextInt UntaggedValue" $+        thEitherTextIntToJSONUntaggedValue `sameAs` thEitherTextIntToEncodingUntaggedValue+       , testProperty "SomeType2ElemArray" $         thSomeTypeToJSON2ElemArray `sameAs` thSomeTypeToEncoding2ElemArray+      , testProperty "SomeType2ElemArray unary" $+        thSomeTypeLiftToJSON2ElemArray `sameAs1` thSomeTypeLiftToEncoding2ElemArray+      , testProperty "SomeType2ElemArray unary agree" $+        thSomeTypeToEncoding2ElemArray `sameAs1Agree` thSomeTypeLiftToEncoding2ElemArray+       , testProperty "SomeTypeTaggedObject" $         thSomeTypeToJSONTaggedObject `sameAs` thSomeTypeToEncodingTaggedObject+      , testProperty "SomeTypeTaggedObject unary" $+        thSomeTypeLiftToJSONTaggedObject `sameAs1` thSomeTypeLiftToEncodingTaggedObject+      , testProperty "SomeTypeTaggedObject unary agree" $+        thSomeTypeToEncodingTaggedObject `sameAs1Agree` thSomeTypeLiftToEncodingTaggedObject+       , testProperty "SomeTypeObjectWithSingleField" $-        thSomeTypeToJSONObjectWithSingleField `sameAs`-        thSomeTypeToEncodingObjectWithSingleField+        thSomeTypeToJSONObjectWithSingleField `sameAs` thSomeTypeToEncodingObjectWithSingleField+      , testProperty "SomeTypeObjectWithSingleField unary" $+        thSomeTypeLiftToJSONObjectWithSingleField `sameAs1` thSomeTypeLiftToEncodingObjectWithSingleField+      , testProperty "SomeTypeObjectWithSingleField unary agree" $+        thSomeTypeToEncodingObjectWithSingleField `sameAs1Agree` thSomeTypeLiftToEncodingObjectWithSingleField       ]     ]   ]
tests/Tests.hs view
@@ -1,5 +1,8 @@ module Main (main) where +import Prelude ()+import Prelude.Compat+ import Test.Framework (defaultMain) import qualified DataFamilies.Properties as DF import qualified Properties
tests/Types.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-}@@ -7,12 +8,21 @@  module Types where -import qualified Data.Map as Map+import Prelude ()+import Prelude.Compat+ import Data.Data+import Data.Functor.Compose (Compose (..))+import Data.Functor.Identity (Identity (..)) import Data.Text import GHC.Generics import Test.QuickCheck (Property, counterexample)+import qualified Data.Map as Map +type I = Identity+type Compose3  f g h = Compose (Compose f g) h+type Compose3' f g h = Compose f (Compose g h)+ data Foo = Foo {       fooInt :: Int     , fooDouble :: Double@@ -56,8 +66,18 @@                 | Record { testOne   :: Double                          , testTwo   :: Maybe Bool                          , testThree :: Maybe a-                         } deriving (Eq, Show)+                         }+                | List [a]+  deriving (Eq, Show) +-- Used for testing UntaggedValue SumEncoding+data EitherTextInt+    = LeftBool Bool+    | RightInt Int+    | BothTextInt Text Int+    | NoneNullary+    deriving (Eq, Show)+ data GADT a where     GADT :: { gadt :: String } -> GADT String   deriving Typeable@@ -75,6 +95,10 @@ deriving instance Generic (Approx a) deriving instance Generic Nullary deriving instance Generic (SomeType a)+#if __GLASGOW_HASKELL__ >= 706+deriving instance Generic1 SomeType+#endif+deriving instance Generic EitherTextInt  failure :: Show a => String -> String -> a -> Property failure func msg v = counterexample
tests/UnitTests.hs view
@@ -1,40 +1,72 @@-{-# LANGUAGE CPP, DeriveGeneric, OverloadedStrings, ScopedTypeVariables, TemplateHaskell #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE DataKinds #-}+#endif  {-# OPTIONS_GHC -fno-warn-deprecations #-} -module UnitTests (ioTests, tests) where+module UnitTests+    (+      ioTests+    , tests+    ) where +import Prelude ()+import Prelude.Compat+ import Control.Applicative (Const(..)) import Control.Monad (forM)-import Data.Aeson (decode, eitherDecode, encode, genericToJSON, genericToEncoding, object, FromJSON(..), withObject, (.=), (.:), (.:?), (.:!))-import Data.Aeson.Encode (encodeToTextBuilder)+import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, genericParseJSON, genericToEncoding, genericToJSON, object, withObject) import Data.Aeson.Internal (JSONPathElement(..), formatError)-import Data.Aeson.TH (deriveJSON)-import Data.Aeson.Types (ToJSON(..), Value, camelTo, camelTo2, defaultOptions, omitNothingFields)+import Data.Aeson.TH (deriveJSON, deriveToJSON, deriveToJSON1)+import Data.Aeson.Text (encodeToTextBuilder)+import Data.Aeson.Types (Options(..), SumEncoding(..), ToJSON(..), Value, camelTo, camelTo2, defaultOptions, omitNothingFields) import Data.Char (toUpper)+import Data.Fixed (Pico)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))+import Data.Functor.Product (Product(..))+import Data.Functor.Sum (Sum(..)) import Data.Hashable (hash) import Data.List.NonEmpty (NonEmpty(..)) import Data.Maybe (fromMaybe) import Data.Proxy (Proxy(..))+import Data.Scientific (Scientific) import Data.Sequence (Seq) import Data.Tagged (Tagged(..))+import Data.Text (Text) import Data.Time (UTCTime) import Data.Time.Format (parseTime)+import Data.Time.Locale.Compat (defaultTimeLocale)+import Data.Word (Word8) import GHC.Generics (Generic)+import Instances () import Test.Framework (Test, testGroup) import Test.Framework.Providers.HUnit (testCase) import Test.HUnit (Assertion, assertFailure, assertEqual)+import Types (Approx(..), Compose3, Compose3', I)+import UnitTests.NullaryConstructors (nullaryConstructors) import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.Text.Lazy.Builder as TLB-import qualified Data.Text.Lazy.Encoding as TLE+import qualified Data.DList as DList+import qualified Data.HashMap.Strict as HM+import qualified Data.HashSet as HashSet+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Map as M+import qualified Data.Sequence as Seq+import qualified Data.Set as Set import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Builder as TLB import qualified Data.Text.Lazy.Encoding as LT--#if MIN_VERSION_time(1,5,0)-import Data.Time.Format (defaultTimeLocale)-#else-import System.Locale (defaultTimeLocale)-#endif+import qualified Data.Text.Lazy.Encoding as TLE+import qualified Data.Tree as Tree+import qualified Data.Vector as Vector  tests :: Test tests = testGroup "unit" [@@ -61,11 +93,15 @@       testCase "example 1" $ formatErrorExample     ]   , testGroup ".:, .:?, .:!" $ fmap (testCase "-") dotColonMark-  , testGroup "To JSON representation" $ fmap (testCase "-") jsonEncoding-  , testGroup "From JSON representation" $ fmap (testCase "-") jsonDecoding+  , testGroup "To JSON representation" $ fmap assertJsonEncodingExample jsonEncodingExamples+  , testGroup "From JSON representation" $ fmap assertJsonExample jsonDecodingExamples+  , testGroup "To/From JSON representation" $ fmap assertJsonExample jsonExamples   , testGroup "JSONPath" $ fmap (testCase "-") jsonPath   , testGroup "Hashable laws" $ fmap (testCase "-") hashableLaws   , testGroup "Issue #351" $ fmap (testCase "-") issue351+  , testGroup "Nullary constructors" $ fmap (testCase "-") nullaryConstructors+  , testGroup "FromJSONKey" $ fmap (testCase "-") fromJSONKeyAssertions+  , testCase "PR #455" pr455   ]  roundTripCamel :: String -> Assertion@@ -81,11 +117,25 @@     split c' s' = map L.unpack $ L.split c' $ L.pack s'     capitalize t = toUpper (head t) : tail t ++data MyEither a b = MyLeft a | MyRight b+  deriving (Generic, Show, Eq)++instance (ToJSON a, ToJSON b) => ToJSON (MyEither a b) where+    toJSON = genericToJSON defaultOptions { sumEncoding = UntaggedValue }+    toEncoding = genericToEncoding defaultOptions { sumEncoding = UntaggedValue }++instance (FromJSON a, FromJSON b) => FromJSON (MyEither a b) where+    parseJSON = genericParseJSON defaultOptions { sumEncoding = UntaggedValue }++ data Wibble = Wibble {     wibbleString :: String   , wibbleInt :: Int-  } deriving (Generic, Show)+  } deriving (Generic, Show, Eq) +instance FromJSON Wibble+ instance ToJSON Wibble where     toJSON     = genericToJSON defaultOptions     toEncoding = genericToEncoding defaultOptions@@ -222,30 +272,157 @@ -- These tests assert that the JSON serialization doesn't change by accident. ----------------------------------------------------------------------------- -jsonEncoding :: [Assertion]-jsonEncoding = [-    assertEqual "Either Left" "{\"Left\":1}" $ encode (Left 1 :: Either Int Int)-  , assertEqual "Either Right" "{\"Right\":1}" $ encode (Right 1 :: Either Int Int)-  , assertEqual "Nothing"  "null" $ encode (Nothing :: Maybe Int)-  , assertEqual "Just"  "1" $ encode (Just 1 :: Maybe Int)-  , assertEqual "Just Nothing" "null" $ encode (Just Nothing :: Maybe (Maybe Int))-  , assertEqual "Proxy Int" "null" $ encode (Proxy :: Proxy Int)-  , assertEqual "Tagged Char Int" "1" $ encode (Tagged 1 :: Tagged Char Int)-  , assertEqual "Const Char Int" "\"c\"" $ encode (Const 'c' :: Const Char Int)-  , assertEqual "Tuple" "[1,2]" $ encode ((1, 2) :: (Int, Int))-  , assertEqual "NonEmpty" "[1,2,3]" $ encode (1 :| [2, 3] :: NonEmpty Int)-  , assertEqual "()" "[]" $ encode ()+data Example where+    Example+        :: (Eq a, Show a, ToJSON a, FromJSON a)+        => String -> L.ByteString -> a -> Example+    MaybeExample+        :: (Eq a, Show a, FromJSON a)+        => String -> L.ByteString -> Maybe a -> Example++assertJsonExample :: Example -> Test+assertJsonExample (Example name bs val) = testCase name $ do+    assertEqual "encode"           bs         (encode val)+    assertEqual "encode/via value" bs         (encode $ toJSON val)+    assertEqual "decode"           (Just val) (decode bs)+assertJsonExample (MaybeExample name bs mval) = testCase name $+    assertEqual "decode" mval (decode bs)++assertJsonEncodingExample :: Example -> Test+assertJsonEncodingExample (Example name bs val) = testCase name $ do+    assertEqual "encode"           bs (encode val)+    assertEqual "encode/via value" bs (encode $ toJSON val)+assertJsonEncodingExample (MaybeExample name _ _) = testCase name $+    assertFailure "cannot encode MaybeExample"++jsonEncodingExamples :: [Example]+jsonEncodingExamples =+  [+  -- Maybe serialising is lossy+  -- https://github.com/bos/aeson/issues/376+    Example "Just Nothing" "null" (Just Nothing :: Maybe (Maybe Int))+  -- infinities cannot be recovered, null is decoded as NaN+  , Example "inf :: Double" "null" (Approx $ 1/0 :: Approx Double)   ] -jsonDecoding :: [Assertion]-jsonDecoding = [-    assertEqual "Nothing" (Nothing :: Maybe Int) (decode "null")-  , assertEqual "Just"    (Just 1 :: Maybe Int) (decode "1")-  , assertEqual "Just Nothing" (Just Nothing :: Maybe (Maybe Int)) (decode "null")-  , assertEqual "NonEmpty" (Just (1 :| [2, 3]) :: Maybe (NonEmpty Int)) (decode "[1,2,3]")-  , assertEqual "()" (Just ()) (decode "[]")+jsonDecodingExamples :: [Example]+jsonDecodingExamples = [+  -- Maybe serialising is lossy+  -- https://github.com/bos/aeson/issues/376+    MaybeExample "Nothing"      "null" (Just $ Nothing :: Maybe (Maybe Int))+  , MaybeExample "Just"         "1"    (Just $ Just 1 :: Maybe (Maybe Int))+  , MaybeExample "Just Nothing" "null" (Just $ Nothing :: Maybe (Maybe (Maybe Int)))+  -- Integral values are truncated, and overflowed+  -- https://github.com/bos/aeson/issues/317+  , MaybeExample "Word8 3"    "3"    (Just 3 :: Maybe Word8)+  , MaybeExample "Word8 3.00" "3.00" (Just 3 :: Maybe Word8)+  , MaybeExample "Word8 3.14" "3.14" (Nothing :: Maybe Word8)+  , MaybeExample "Word8 -1"   "-1"   (Nothing :: Maybe Word8)+  , MaybeExample "Word8 300"  "300"  (Nothing :: Maybe Word8)   ] +jsonExamples :: [Example]+jsonExamples =+  [+    Example "Either Left" "{\"Left\":1}"  (Left 1 :: Either Int Int)+  , Example "Either Right" "{\"Right\":1}"  (Right 1 :: Either Int Int)+  , Example "Nothing"  "null"  (Nothing :: Maybe Int)+  , Example "Just"  "1"  (Just 1 :: Maybe Int)+  , Example "Proxy Int" "null"  (Proxy :: Proxy Int)+  , Example "Tagged Char Int" "1"  (Tagged 1 :: Tagged Char Int)+#if __GLASGOW_HASKELL__ >= 708+    -- Test Tagged instance is polykinded+  , Example "Tagged 123 Int" "1"  (Tagged 1 :: Tagged 123 Int)+#endif+  , Example "Const Char Int" "\"c\""  (Const 'c' :: Const Char Int)+  , Example "Tuple" "[1,2]"  ((1, 2) :: (Int, Int))+  , Example "NonEmpty" "[1,2,3]"  (1 :| [2, 3] :: NonEmpty Int)+  , Example "Seq" "[1,2,3]"  (Seq.fromList [1, 2, 3] ::  Seq.Seq Int)+  , Example "DList" "[1,2,3]"  (DList.fromList [1, 2, 3] :: DList.DList Int)+  , Example "()" "[]"  ()++  , Example "HashMap Int Int"          "{\"0\":1,\"2\":3}"  (HM.fromList [(0,1),(2,3)] :: HM.HashMap Int Int)+  , Example "Map Int Int"              "{\"0\":1,\"2\":3}"  (M.fromList [(0,1),(2,3)] :: M.Map Int Int)+  , Example "Map (Tagged Int Int) Int" "{\"0\":1,\"2\":3}"  (M.fromList [(Tagged 0,1),(Tagged 2,3)] :: M.Map (Tagged Int Int) Int)+  , Example "Map [Int] Int"            "[[[0],1],[[2],3]]"  (M.fromList [([0],1),([2],3)] :: M.Map [Int] Int)+  , Example "Map [Char] Int"           "{\"ab\":1,\"cd\":3}"  (M.fromList [("ab",1),("cd",3)] :: M.Map [Char] Int)+  , Example "Map [I Char] Int"         "{\"ab\":1,\"cd\":3}"  (M.fromList [(map pure "ab",1),(map pure "cd",3)] :: M.Map [I Char] Int)++  , Example "nan :: Double" "null"  (Approx $ 0/0 :: Approx Double)++  , Example "Ordering LT" "\"LT\"" LT+  , Example "Ordering EQ" "\"EQ\"" EQ+  , Example "Ordering GT" "\"GT\"" GT++  , Example "Float" "3.14" (3.14 :: Float)+  , Example "Pico" "3.14" (3.14 :: Pico)+  , Example "Scientific" "3.14" (3.14 :: Scientific)++  , Example "Set Int" "[1,2,3]" (Set.fromList [3, 2, 1] :: Set.Set Int)+  , Example "IntSet"  "[1,2,3]" (IntSet.fromList [3, 2, 1])+  , Example "IntMap" "[[1,2],[3,4]]" (IntMap.fromList [(3,4), (1,2)] :: IntMap.IntMap Int)+  , Example "Vector" "[1,2,3]" (Vector.fromList [1, 2, 3] :: Vector.Vector Int)+  , Example "HashSet Int" "[1,2,3]" (HashSet.fromList [3, 2, 1] :: HashSet.HashSet Int)+  , Example "Tree Int" "[1,[[2,[[3,[]],[4,[]]]],[5,[]]]]" (let n = Tree.Node in n 1 [n 2 [n 3 [], n 4 []], n 5 []] :: Tree.Tree Int)++  -- Three separate cases, as ordering in HashMap is not defined+  , Example "HashMap Float Int, NaN" "{\"NaN\":1}"  (Approx $ HM.singleton (0/0) 1 :: Approx (HM.HashMap Float Int))+  , Example "HashMap Float Int, Infinity" "{\"Infinity\":1}"  (HM.singleton (1/0) 1 :: HM.HashMap Float Int)+  , Example "HashMap Float Int, +Infinity" "{\"-Infinity\":1}"  (HM.singleton (negate 1/0) 1 :: HM.HashMap Float Int)++  -- Functors+  , Example "Identity Int" "1"  (pure 1 :: Identity Int)++  , Example "Identity Char" "\"x\""      (pure 'x' :: Identity Char)+  , Example "Identity String" "\"foo\""  (pure "foo" :: Identity String)+  , Example "[Identity Char]" "\"xy\""   ([pure 'x', pure 'y'] :: [Identity Char])++  , Example "Maybe Char" "\"x\""              (pure 'x' :: Maybe Char)+  , Example "Maybe String" "\"foo\""          (pure "foo" :: Maybe String)+  , Example "Maybe [Identity Char]" "\"xy\""  (pure [pure 'x', pure 'y'] :: Maybe [Identity Char])++  , Example "Product I Maybe Int" "[1,2]"         (Pair (pure 1) (pure 2) :: Product I Maybe Int)+  , Example "Product I Maybe Int" "[1,null]"      (Pair (pure 1) Nothing :: Product I Maybe Int)+  , Example "Product I [] Char" "[\"a\",\"foo\"]" (Pair (pure 'a') "foo" :: Product I [] Char)++  , Example "Sum I [] Int: InL"  "{\"InL\":1}"       (InL (pure 1) :: Sum I [] Int)+  , Example "Sum I [] Int: InR"  "{\"InR\":[1,2]}"   (InR [1, 2] :: Sum I [] Int)+  , Example "Sum I [] Char: InR" "{\"InR\":\"foo\"}" (InR "foo" :: Sum I [] Char)++  , Example "Compose I  I  Int" "1"      (pure 1 :: Compose I I   Int)+  , Example "Compose I  [] Int" "[1]"    (pure 1 :: Compose I []  Int)+  , Example "Compose [] I  Int" "[1]"    (pure 1 :: Compose [] I  Int)+  , Example "Compose [] [] Int" "[[1]]"  (pure 1 :: Compose [] [] Int)++  , Example "Compose I  I  Char" "\"x\""    (pure 'x' :: Compose I  I  Char)+  , Example "Compose I  [] Char" "\"x\""    (pure 'x' :: Compose I  [] Char)+  , Example "Compose [] I  Char" "\"x\""    (pure 'x' :: Compose [] I  Char)+  , Example "Compose [] [] Char" "[\"x\"]"  (pure 'x' :: Compose [] [] Char)++  , Example "Compose3 I  I  I  Char" "\"x\""      (pure 'x' :: Compose3 I  I  I  Char)+  , Example "Compose3 I  I  [] Char" "\"x\""      (pure 'x' :: Compose3 I  I  [] Char)+  , Example "Compose3 I  [] I  Char" "\"x\""      (pure 'x' :: Compose3 I  [] I  Char)+  , Example "Compose3 I  [] [] Char" "[\"x\"]"    (pure 'x' :: Compose3 I  [] [] Char)+  , Example "Compose3 [] I  I  Char" "\"x\""      (pure 'x' :: Compose3 [] I  I  Char)+  , Example "Compose3 [] I  [] Char" "[\"x\"]"    (pure 'x' :: Compose3 [] I  [] Char)+  , Example "Compose3 [] [] I  Char" "[\"x\"]"    (pure 'x' :: Compose3 [] [] I  Char)+  , Example "Compose3 [] [] [] Char" "[[\"x\"]]"  (pure 'x' :: Compose3 [] [] [] Char)++  , Example "Compose3' I  I  I  Char" "\"x\""      (pure 'x' :: Compose3' I  I  I  Char)+  , Example "Compose3' I  I  [] Char" "\"x\""      (pure 'x' :: Compose3' I  I  [] Char)+  , Example "Compose3' I  [] I  Char" "\"x\""      (pure 'x' :: Compose3' I  [] I  Char)+  , Example "Compose3' I  [] [] Char" "[\"x\"]"    (pure 'x' :: Compose3' I  [] [] Char)+  , Example "Compose3' [] I  I  Char" "\"x\""      (pure 'x' :: Compose3' [] I  I  Char)+  , Example "Compose3' [] I  [] Char" "[\"x\"]"    (pure 'x' :: Compose3' [] I  [] Char)+  , Example "Compose3' [] [] I  Char" "[\"x\"]"    (pure 'x' :: Compose3' [] [] I  Char)+  , Example "Compose3' [] [] [] Char" "[[\"x\"]]"  (pure 'x' :: Compose3' [] [] [] Char)++  , Example "MyEither Int String: Left"  "42"      (MyLeft 42     :: MyEither Int String)+  , Example "MyEither Int String: Right" "\"foo\"" (MyRight "foo" :: MyEither Int String)+  ]+++ ------------------------------------------------------------------------------ -- These tests check that JSONPath is tracked correctly -----------------------------------------------------------------------------@@ -261,6 +438,10 @@   , assertEqual "Seq a"       (Left "Error in $[2]: expected Int, encountered Boolean")       (eitherDecode "[0,1,true]" :: Either String (Seq Int))+  , assertEqual "Wibble"+      (Left "Error in $.wibbleInt: expected Int, encountered Boolean")+      (eitherDecode "{\"wibbleString\":\"\",\"wibbleInt\":true}"+         :: Either String Wibble)   ]  ------------------------------------------------------------------------------@@ -275,6 +456,47 @@   a = object ["223" .= False, "807882556" .= True]   b = object ["807882556" .= True, "223" .= False] +-------------------------------------------------------------------------------+-- ToJSONKey+-------------------------------------------------------------------------------++newtype MyText = MyText Text+    deriving (FromJSONKey)++newtype MyText' = MyText' Text++instance FromJSONKey MyText' where+    fromJSONKey = fmap MyText' fromJSONKey+    fromJSONKeyList = error "not used"++fromJSONKeyAssertions :: [Assertion]+fromJSONKeyAssertions =+    [ assertIsCoerce  "Text"            (fromJSONKey :: FromJSONKeyFunction Text)+    , assertIsCoerce  "Tagged Int Text" (fromJSONKey :: FromJSONKeyFunction (Tagged Int Text))+    , assertIsCoerce  "MyText"          (fromJSONKey :: FromJSONKeyFunction MyText)++#if __GLASGOW_HASKELL__ >= 710+    , assertIsCoerce' "MyText'"         (fromJSONKey :: FromJSONKeyFunction MyText')+#endif+    ]+  where+    assertIsCoerce _ (FromJSONKeyCoerce _) = pure ()+    assertIsCoerce n _                     = assertFailure n++#if __GLASGOW_HASKELL__ >= 710+    assertIsCoerce' _ (FromJSONKeyCoerce _) = pure ()+    assertIsCoerce' n _                     = pickWithRules (assertFailure n) (pure ())++-- | Pick the first when RULES are enabled, e.g. optimisations are on+pickWithRules+    :: a -- ^ Pick this when RULES are on+    -> a -- ^ use this otherwise+    -> a+pickWithRules _ = id+{-# NOINLINE pickWithRules #-}+{-# RULES "pickWithRules/rule" [0] forall x. pickWithRules x = const x #-}+#endif+ ------------------------------------------------------------------------------ -- Regressions ------------------------------------------------------------------------------@@ -286,8 +508,8 @@ issue351 :: [Assertion] issue351 = [     assertEqual "Int"  ([1, 2, 3] :: [Int])  $ overlappingRegression "[1, 2, 3]"-  , assertEqual "Char" (""        :: String) $ overlappingRegression "\"abc\""-  , assertEqual "Char" ("abc"     :: String) $ overlappingRegression "[\"a\", \"b\", \"c\"]"+  , assertEqual "Char" ("abc"     :: String) $ overlappingRegression "\"abc\""+  , assertEqual "Char" (""        :: String) $ overlappingRegression "[\"a\", \"b\", \"c\"]"   ]  ------------------------------------------------------------------------------@@ -331,10 +553,24 @@  -- A regression test for: https://github.com/bos/aeson/issues/293 data MyRecord = MyRecord {_field1 :: Maybe Int, _field2 :: Maybe Bool}-deriveJSON defaultOptions{omitNothingFields=True} ''MyRecord  data MyRecord2 = MyRecord2 {_field3 :: Maybe Int, _field4 :: Maybe Bool}   deriving Generic  instance ToJSON   MyRecord2 instance FromJSON MyRecord2++-- A regression test for: https://github.com/bos/aeson/pull/455+data Foo a = FooNil | FooCons (Foo Int)++pr455 :: Assertion+pr455 = assertEqual "FooCons FooNil"+          (toJSON foo) (liftToJSON undefined undefined foo)+  where+    foo :: Foo Int+    foo = FooCons FooNil++deriveJSON defaultOptions{omitNothingFields=True} ''MyRecord++deriveToJSON  defaultOptions ''Foo+deriveToJSON1 defaultOptions ''Foo
+ tests/UnitTests/NullaryConstructors.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE  OverloadedStrings #-}++{-# OPTIONS_GHC -fno-warn-deprecations #-}++module UnitTests.NullaryConstructors+    (+      nullaryConstructors+    ) where++import Prelude ()+import Prelude.Compat++import Data.Aeson (decode, eitherDecode, fromEncoding, Value)+import Data.Aeson.Internal (IResult (..), iparse)+import Data.Aeson.Types (Parser)+import Data.ByteString.Builder (toLazyByteString)+import Data.Maybe (fromJust)+import Encoders+import Test.HUnit ((@=?), Assertion)+import Types+import qualified Data.ByteString.Lazy.Char8 as L++nullaryConstructors :: [Assertion]+nullaryConstructors =+  [ dec "\"C1\""           @=? thNullaryToJSONString C1+  , dec "\"C1\""           @=? gNullaryToJSONString C1+  , dec "{\"c1\":[]}"      @=? thNullaryToJSONObjectWithSingleField C1+  , dec "{\"c1\":[]}"      @=? gNullaryToJSONObjectWithSingleField C1+  , dec "[\"c1\",[]]"      @=? gNullaryToJSON2ElemArray C1+  , dec "[\"c1\",[]]"      @=? thNullaryToJSON2ElemArray C1+  , dec "{\"tag\":\"c1\"}" @=? thNullaryToJSONTaggedObject C1+  , dec "{\"tag\":\"c1\"}" @=? gNullaryToJSONTaggedObject C1++  , decE "\"C1\""           @=? enc (gNullaryToEncodingString C1)+  , decE "\"C1\""           @=? enc (thNullaryToEncodingString C1)+  , decE "[\"c1\",[]]"      @=? enc (gNullaryToEncoding2ElemArray C1)+  , decE "[\"c1\",[]]"      @=? enc (thNullaryToEncoding2ElemArray C1)+  , decE "{\"c1\":[]}"      @=? enc (thNullaryToEncodingObjectWithSingleField C1)+  , decE "{\"c1\":[]}"      @=? enc (gNullaryToEncodingObjectWithSingleField C1)+  , decE "{\"tag\":\"c1\"}" @=? enc (thNullaryToEncodingTaggedObject C1)+  , decE "{\"tag\":\"c1\"}" @=? enc (gNullaryToEncodingTaggedObject C1)++  , ISuccess C1 @=? parse thNullaryParseJSONTaggedObject          (dec "{\"tag\":\"c1\"}")+  , ISuccess C1 @=? parse gNullaryParseJSONTaggedObject           (dec "{\"tag\":\"c1\"}")++  , ISuccess C1 @=? parse thNullaryParseJSONString                (dec "\"C1\"")+  , ISuccess C1 @=? parse gNullaryParseJSONString                 (dec "\"C1\"")+  , ISuccess C1 @=? parse thNullaryParseJSON2ElemArray            (dec  "[\"c1\",[]]")+  , ISuccess C1 @=? parse gNullaryParseJSON2ElemArray             (dec  "[\"c1\",[]]")+  , ISuccess C1 @=? parse thNullaryParseJSONObjectWithSingleField (dec  "{\"c1\":[]}")+  , ISuccess C1 @=? parse gNullaryParseJSONObjectWithSingleField  (dec  "{\"c1\":[]}")+    -- Make sure that the old `"contents" : []' is still allowed+  , ISuccess C1 @=? parse thNullaryParseJSONTaggedObject          (dec "{\"tag\":\"c1\",\"contents\":[]}")+  , ISuccess C1 @=? parse gNullaryParseJSONTaggedObject           (dec "{\"tag\":\"c1\",\"contents\":[]}")+  ]+  where+    enc = eitherDecode . toLazyByteString . fromEncoding+    dec :: L.ByteString -> Value+    dec = fromJust . decode+    decE :: L.ByteString -> Either String Value+    decE = eitherDecode+    parse :: (a -> Parser b) -> a -> IResult b+    parse parsejson v = iparse parsejson v