@@ -43,6 +43,7 @@ module Data.Aeson.Types.ToJSON (
4343 -- * Classes and types for map keys
4444 , ToJSONKey(..)
4545 , ToJSONKeyFunction(..)
46+ , toJSONKeyText
4647 , contramapToJSONKeyFunction
4748 -- * Object key-value pairs
4849 , KeyValue(..)
@@ -55,9 +56,9 @@ module Data.Aeson.Types.ToJSON (
5556import Prelude ()
5657import Prelude.Compat
5758
58−import Data.Aeson.Encoding.Internal (Encoding (..), Series, dict, emptyArray_,
59− tuple, (>*<))
60−import Data.Aeson.Functions (mapHashKeyVal, mapKeyVal)
59+import Data.Aeson.Encoding.Internal (Encoding, Encoding', Series, dict,
60+ emptyArray_, tuple, (>*<), (><))
61+import Data.Aeson.Internal.Functions (mapHashKeyVal, mapKeyVal)
6162import Data.Aeson.Types.Generic
6263import Data.Aeson.Types.Internal
6364
@@ -71,6 +72,7 @@ import Data.Bits (unsafeShiftR)
7172import Data.DList (DList)
7273import Data.Fixed (Fixed, HasResolution)
7374import Data.Foldable (toList)
75+import Data.Functor.Compose (Compose (..))
7476import Data.Functor.Identity (Identity (..))
7577import Data.Int (Int16, Int32, Int64, Int8)
7678import Data.List (intersperse)
@@ -92,35 +94,30 @@ import Foreign.Storable (Storable)
9294import GHC.Generics
9395import Numeric.Natural (Natural)
9496
95−import qualified Data.ByteString.Builder as B (toLazyByteString)
96−import qualified Data.ByteString.Lazy as L
97−import qualified Data.DList as DList
98−import qualified Data.HashMap.Strict as H
99−import qualified Data.HashSet as HashSet
100−import qualified Data.IntMap as IntMap
101−import qualified Data.IntSet as IntSet
102−import qualified Data.List.NonEmpty as NE
103−import qualified Data.Map as M
104−import qualified Data.Scientific as Scientific
105−import qualified Data.Sequence as Seq
106−import qualified Data.Set as Set
107−import qualified Data.Text as T
108−import qualified Data.Text.Encoding as T
109−import qualified Data.Text.Lazy as LT
110−import qualified Data.Tree as Tree
111−import qualified Data.Vector as V
112−import qualified Data.Vector.Generic as VG
113−import qualified Data.Vector.Mutable as VM
114−import qualified Data.Vector.Primitive as VP
115−import qualified Data.Vector.Storable as VS
116−import qualified Data.Vector.Unboxed as VU
97+import qualified Data.ByteString.Lazy as L
98+import qualified Data.DList as DList
99+import qualified Data.HashMap.Strict as H
100+import qualified Data.HashSet as HashSet
101+import qualified Data.IntMap as IntMap
102+import qualified Data.IntSet as IntSet
103+import qualified Data.List.NonEmpty as NE
104+import qualified Data.Map as M
105+import qualified Data.Scientific as Scientific
106+import qualified Data.Sequence as Seq
107+import qualified Data.Set as Set
108+import qualified Data.Text as T
109+import qualified Data.Text.Encoding as T
110+import qualified Data.Text.Lazy as LT
111+import qualified Data.Tree as Tree
112+import qualified Data.Vector as V
113+import qualified Data.Vector.Generic as VG
114+import qualified Data.Vector.Mutable as VM
115+import qualified Data.Vector.Primitive as VP
116+import qualified Data.Vector.Storable as VS
117+import qualified Data.Vector.Unboxed as VU
117118
118119toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value
119−toJSONPair keySerialiser valSerializer (a, b) = Array $ V.create $ do
120− mv <- VM.unsafeNew 2
121− VM.unsafeWrite mv 0 (keySerialiser a)
122− VM.unsafeWrite mv 1 (valSerializer b)
123− return mv
120+toJSONPair a b = liftToJSON2 a (listValue a) b (listValue b)
124121{-# INLINE toJSONPair #-}
125122
126123realFloatToJSON :: RealFloat a => a -> Value
@@ -309,7 +306,7 @@ instance KeyValue Pair where
309306
310307-- | Typeclass for types that can be used as the key of a map-like container
311308-- (like 'Map' or 'HashMap'). For example, since 'Text' has a 'ToJSONKey'
312−-- instance and 'Char' has a 'ToJSON' instance, we can encode a value of
309+-- instance and 'Char' has a 'ToJSON' instance, we can encode a value of
313310-- type 'Map' 'Text' 'Char':
314311--
315312-- >>> LBC8.putStrLn $ encode $ Map.fromList [("foo" :: Text, 'a')]
@@ -355,16 +352,16 @@ instance KeyValue Pair where
355352-- >>> let m = Map.fromList [(Foo 4 "bar",'a'),(Foo 6 "arg",'b')]
356353-- >>> LBC8.putStrLn $ encode m
357354-- [[{"fooName":"bar","fooAge":4},"a"],[{"fooName":"arg","fooAge":6},"b"]]
358−--
355+--
359356-- The next case to consider is if we have a type that is a
360357-- newtype wrapper around 'Text'. The recommended approach is to use
361358-- generalized newtype deriving:
362359--
363360-- > newtype RecordId = RecordId { getRecordId :: Text}
364361-- > deriving (Eq,Ord,ToJSONKey)
365−--
362+--
366363-- Then we may write:
367−--
364+--
368365-- >>> LBC8.putStrLn $ encode $ Map.fromList [(RecordId "abc",'a')]
369366-- {"abc":"a"}
370367--
@@ -382,7 +379,7 @@ instance KeyValue Pair where
382379-- > instance ToJSONKey Color where
383380-- > toJSONKey = ToJSONKeyText f g
384381-- > where f = Text.pack . show
385−-- > g = text . Text.pack . show
382+-- > g = text . Text.pack . show
386383-- > -- text function is from Data.Aeson.Encoding
387384--
388385-- The situation of needing to turning function @a -> Text@ into
@@ -391,7 +388,7 @@ instance KeyValue Pair where
391388--
392389-- > instance ToJSONKey Color where
393390-- > toJSONKey = toJSONKeyText (Text.pack . show)
394−--
391+--
395392-- The performance of the above instance can be improved by
396393-- not using 'String' as an intermediate step when converting to
397394-- 'Text'. One option for improving performance would be to use
@@ -400,7 +397,7 @@ instance KeyValue Pair where
400397-- builder) is generated by encoding the 'Text' to a 'ByteString',
401398-- an intermediate step that could be avoided. The fastest possible
402399-- implementation would be:
403−--
400+--
404401-- > -- Assuming that OverloadedStrings is enabled
405402-- > instance ToJSONKey Color where
406403-- > toJSONKey = ToJSONKeyText f g
@@ -417,23 +414,45 @@ class ToJSONKey a where
417414 -- | Strategy for rendering the key for a map-like container.
418415 toJSONKey :: ToJSONKeyFunction a
419416 default toJSONKey :: ToJSON a => ToJSONKeyFunction a
420− toJSONKey = ToJSONKeyValue (toJSON, toEncoding)
417+ toJSONKey = ToJSONKeyValue toJSON toEncoding
418+
421419 -- | This is similar in spirit to the 'showsList' method of 'Show'.
422420 -- It makes it possible to give 'String' keys special treatment
423421 -- without using @OverlappingInstances@. End users should always
424422 -- be able to use the default implementation of this method.
425423 toJSONKeyList :: ToJSONKeyFunction [a]
426424 default toJSONKeyList :: ToJSON a => ToJSONKeyFunction [a]
427− toJSONKeyList = ToJSONKeyValue (toJSON, toEncoding)
425+ toJSONKeyList = ToJSONKeyValue toJSON toEncoding
428426
429427data ToJSONKeyFunction a
430− = ToJSONKeyText (a -> Text, a -> Encoding) -- ^ key is encoded to string, produces object
431− | ToJSONKeyValue (a -> Value, a -> Encoding) -- ^ key is encoded to value, produces array
428+ = ToJSONKeyText !(a -> Text) !(a -> Encoding' Text)
429+ -- ^ key is encoded to string, produces object
430+ | ToJSONKeyValue !(a -> Value) !(a -> Encoding)
431+ -- ^ key is encoded to value, produces array
432432
433+-- | Helper for creating textual keys.
434+--
435+-- @
436+-- instance 'ToJSONKey' MyKey where
437+-- 'toJSONKey' = 'toJSONKeyText' myKeyToText
438+-- where
439+-- myKeyToText = Text.pack . show -- or showt from text-show
440+-- @
441+toJSONKeyText :: (a -> Text) -> ToJSONKeyFunction a
442+toJSONKeyText f = ToJSONKeyText f (E.text . f)
443+
444+-- | TODO: should this be exported?
445+toJSONKeyTextEnc :: (a -> Encoding' Text) -> ToJSONKeyFunction a
446+toJSONKeyTextEnc e = ToJSONKeyText tot e
447+ where
448+ -- TODO: dropAround is also used in stringEncoding, which is unfortunate atm
449+ tot = T.dropAround (== '"') . T.decodeLatin1 . L.toStrict . E.encodingToLazyByteString . e
450+
451+-- | Contravariant map, as 'ToJSONKeyFunction' is a contravariant functor.
433452contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b
434453contramapToJSONKeyFunction h x = case x of
435− ToJSONKeyText (f,g) -> ToJSONKeyText (f . h, g . h)
436− ToJSONKeyValue (f,g) -> ToJSONKeyValue (f . h, g . h)
454+ ToJSONKeyText f g -> ToJSONKeyText (f . h) (g . h)
455+ ToJSONKeyValue f g -> ToJSONKeyValue (f . h) (g . h)
437456
438457-------------------------------------------------------------------------------
439458-- Lifings of FromJSON and ToJSON to unary and binary type constructors
@@ -676,7 +695,7 @@ instance ( AllNullary (a :+: b) allNullary
676695 -- 'allNullaryToStringTag' option is set they are encoded to
677696 -- strings. This distinction is made by 'sumToEncoding':
678697 gToEncoding opts pa te tel
679− = (unTagged :: Tagged allNullary Encoding -> Encoding)
698+ = (unTagged :: Tagged allNullary (Encoding) -> Encoding)
680699 . sumToEncoding opts pa te tel
681700
682701instance (ToJSON1 f, GToEncoding One g) => GToEncoding One (f :.: g) where
@@ -728,7 +747,7 @@ nonAllNullarySumToJSON opts pa tj tjl =
728747class SumToEncoding arity f allNullary where
729748 sumToEncoding :: Options -> Proxy arity
730749 -> (a -> Encoding) -> ([a] -> Encoding)
731− -> f a -> Tagged allNullary Encoding
750+ -> f a -> Tagged allNullary (Encoding)
732751
733752instance ( GetConName f
734753 , TaggedObjectEnc arity f
@@ -822,29 +841,28 @@ instance ( IsRecord a isRecord
822841 , Constructor c
823842 ) => TaggedObjectEnc arity (C1 c a) where
824843 taggedObjectEnc opts pa tagFieldName contentsFieldName te tel v =
825− E.openCurly <>
826− (toEncoding tagFieldName <>
827− E.colon <>
828− toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))) <>
829− ((unTagged :: Tagged isRecord Encoding -> Encoding) .
830− taggedObjectEnc' opts pa contentsFieldName te tel . unM1 $ v) <>
831− E.closeCurly
844+ E.wrapObject $
845+ (E.string tagFieldName ><
846+ E.colon ><
847+ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))) ><
848+ ((unTagged :: Tagged isRecord (Encoding) -> Encoding) .
849+ taggedObjectEnc' opts pa contentsFieldName te tel . unM1 $ v)
832850
833851class TaggedObjectEnc' arity f isRecord where
834852 taggedObjectEnc' :: Options -> Proxy arity
835853 -> String -> (a -> Encoding) -> ([a] -> Encoding)
836− -> f a -> Tagged isRecord Encoding
854+ -> f a -> Tagged isRecord (Encoding)
837855
838856instance OVERLAPPING_ TaggedObjectEnc' arity U1 False where
839− taggedObjectEnc' _ _ _ _ _ _ = Tagged mempty
857+ taggedObjectEnc' _ _ _ _ _ _ = Tagged E.empty
840858
841859instance (RecordToEncoding arity f) => TaggedObjectEnc' arity f True where
842− taggedObjectEnc' opts pa _ te tel = Tagged . (E.comma <>) . fst
860+ taggedObjectEnc' opts pa _ te tel = Tagged . (E.comma ><) . fst
843861 . recordToEncoding opts pa te tel
844862
845863instance (GToEncoding arity f) => TaggedObjectEnc' arity f False where
846864 taggedObjectEnc' opts pa contentsFieldName te tel =
847− Tagged . (\z -> E.comma <> toEncoding contentsFieldName <> E.colon <> z) .
865+ Tagged . (\z -> E.comma >< toEncoding contentsFieldName >< E.colon >< z) .
848866 gToEncoding opts pa te tel
849867
850868--------------------------------------------------------------------------------
@@ -946,13 +964,13 @@ class ConsToEncoding' arity f isRecord where
946964 consToEncoding' :: Options -> Proxy arity
947965 -> Bool -- ^ Are we a record with one field?
948966 -> (a -> Encoding) -> ([a] -> Encoding)
949− -> f a -> Tagged isRecord Encoding
967+ -> f a -> Tagged isRecord (Encoding)
950968
951969instance ( IsRecord f isRecord
952970 , ConsToEncoding' arity f isRecord
953971 ) => ConsToEncoding arity f where
954972 consToEncoding opts pa te tel =
955− (unTagged :: Tagged isRecord Encoding -> Encoding)
973+ (unTagged :: Tagged isRecord (Encoding) -> (Encoding))
956974 . consToEncoding' opts pa (isUnary (undefined :: f a)) te tel
957975
958976instance (RecordToEncoding arity f) => ConsToEncoding' arity f True where
@@ -1003,39 +1021,40 @@ class RecordToEncoding arity f where
10031021 -- of the field (without the key); 'Nothing' otherwise
10041022 recordToEncoding :: Options -> Proxy arity
10051023 -> (a -> Encoding) -> ([a] -> Encoding)
1006− -> f a -> (Encoding, Maybe Encoding)
1024+ -> f a -> (Encoding, Maybe (Encoding))
10071025
10081026instance ( RecordToEncoding arity a
10091027 , RecordToEncoding arity b
10101028 ) => RecordToEncoding arity (a :*: b) where
10111029 recordToEncoding opts pa te tel (a :*: b) | omitNothingFields opts =
1012− (mconcat $ intersperse E.comma $
1030+ (E.econcat $ intersperse E.comma $
10131031 filter (not . E.nullEncoding)
10141032 [ fst (recordToEncoding opts pa te tel a)
10151033 , fst (recordToEncoding opts pa te tel b) ]
10161034 , Nothing)
10171035 recordToEncoding opts pa te tel (a :*: b) =
1018− (fst (recordToEncoding opts pa te tel a) <> E.comma <>
1036+ (fst (recordToEncoding opts pa te tel a) >< E.comma ><
10191037 fst (recordToEncoding opts pa te tel b),
10201038 Nothing)
10211039
1040+
10221041instance (Selector s, GToEncoding arity a) => RecordToEncoding arity (S1 s a) where
10231042 recordToEncoding = fieldToEncoding
10241043
10251044instance OVERLAPPING_ (Selector s, ToJSON a) =>
10261045 RecordToEncoding arity (S1 s (K1 i (Maybe a))) where
10271046 recordToEncoding opts _ _ _ (M1 k1) | omitNothingFields opts
1028− , K1 Nothing <- k1 = (mempty, Nothing)
1047+ , K1 Nothing <- k1 = (E.empty, Nothing)
10291048 recordToEncoding opts pa te tel m1 = fieldToEncoding opts pa te tel m1
10301049
10311050fieldToEncoding :: (Selector s, GToEncoding arity a)
10321051 => Options -> Proxy arity
10331052 -> (p -> Encoding) -> ([p] -> Encoding)
1034− -> S1 s a p -> (Encoding, Maybe Encoding)
1053+ -> S1 s a p -> (Encoding, Maybe (Encoding))
10351054fieldToEncoding opts pa te tel m1 =
10361055 let keyBuilder = toEncoding (fieldLabelModifier opts $ selName m1)
10371056 valueBuilder = gToEncoding opts pa te tel (unM1 m1)
1038− in (keyBuilder <> E.colon <> valueBuilder, Just valueBuilder)
1057+ in (keyBuilder >< E.colon >< valueBuilder, Just valueBuilder)
10391058
10401059--------------------------------------------------------------------------------
10411060
@@ -1070,21 +1089,20 @@ instance OVERLAPPABLE_ (GToJSON arity a) => WriteProduct arity a where
10701089class EncodeProduct arity f where
10711090 encodeProduct :: Options -> Proxy arity
10721091 -> (a -> Encoding) -> ([a] -> Encoding)
1073− -> f a -> Encoding
1092+ -> f a -> Encoding' E.InArray
10741093
10751094instance ( EncodeProduct arity a
10761095 , EncodeProduct arity b
10771096 ) => EncodeProduct arity (a :*: b) where
10781097 encodeProduct opts pa te tel (a :*: b) | omitNothingFields opts =
1079− mconcat $ intersperse E.comma $
1098+ E.econcat $ intersperse E.comma $
10801099 filter (not . E.nullEncoding)
10811100 [encodeProduct opts pa te tel a, encodeProduct opts pa te tel b]
1082− encodeProduct opts pa te tel (a :*: b) = encodeProduct opts pa te tel a <>
1083− E.comma <>
1101+ encodeProduct opts pa te tel (a :*: b) = encodeProduct opts pa te tel a >*<
10841102 encodeProduct opts pa te tel b
10851103
10861104instance OVERLAPPABLE_ (GToEncoding arity a) => EncodeProduct arity a where
1087− encodeProduct opts = gToEncoding opts
1105+ encodeProduct opts pa te tel a = E.retagEncoding $ gToEncoding opts pa te tel a
10881106
10891107--------------------------------------------------------------------------------
10901108
@@ -1130,12 +1148,12 @@ instance ( GToEncoding arity a
11301148 , Constructor c
11311149 ) => ObjectWithSingleFieldEnc arity (C1 c a) where
11321150 objectWithSingleFieldEnc opts pa te tel v =
1133− E.openCurly <>
1151+ E.openCurly ><
11341152 toEncoding
11351153 (constructorTagModifier opts
1136− (conName (undefined :: t c a p))) <>
1137− E.colon <>
1138− gToEncoding opts pa te tel v <>
1154+ (conName (undefined :: t c a p))) ><
1155+ E.colon ><
1156+ gToEncoding opts pa te tel v ><
11391157 E.closeCurly
11401158
11411159-------------------------------------------------------------------------------
@@ -1146,21 +1164,6 @@ instance ( GToEncoding arity a
11461164-- base
11471165-------------------------------------------------------------------------------
11481166
1149−instance ToJSON1 Identity where
1150− liftToJSON t _ (Identity a) = t a
1151− {-# INLINE liftToJSON #-}
1152−
1153− liftToEncoding t _ (Identity a) = t a
1154− {-# INLINE liftToEncoding #-}
1155−
1156−instance (ToJSON a) => ToJSON (Identity a) where
1157− toJSON = toJSON1
1158− {-# INLINE toJSON #-}
1159−
1160− toEncoding = toEncoding1
1161− {-# INLINE toEncoding #-}
1162−
1163−
11641167instance ToJSON2 Const where
11651168 liftToJSON2 t _ _ _ (Const x) = t x
11661169 {-# INLINE liftToJSON2 #-}
@@ -1237,10 +1240,7 @@ instance ToJSON Bool where
12371240 {-# INLINE toEncoding #-}
12381241
12391242instance ToJSONKey Bool where
1240− toJSONKey = ToJSONKeyText
1241− ( (\x -> if x then "true" else "false")
1242− , (\x -> toEncoding $ if x then ("true" :: Text) else "false")
1243− )
1243+ toJSONKey = toJSONKeyText $ \x -> if x then "true" else "false"
12441244
12451245
12461246instance ToJSON Ordering where
@@ -1485,9 +1485,10 @@ instance ToJSON Text where
14851485 {-# INLINE toEncoding #-}
14861486
14871487instance ToJSONKey Text where
1488− toJSONKey = ToJSONKeyText (id, toEncoding)
1488+ toJSONKey = toJSONKeyText id
14891489 {-# INLINE toJSONKey #-}
14901490
1491+
14911492instance ToJSON LT.Text where
14921493 toJSON = String . LT.toStrict
14931494 {-# INLINE toJSON #-}
@@ -1495,6 +1496,10 @@ instance ToJSON LT.Text where
14951496 toEncoding = E.lazyText
14961497 {-# INLINE toEncoding #-}
14971498
1499+instance ToJSONKey LT.Text where
1500+ toJSONKey = toJSONKeyText LT.toStrict
1501+
1502+
14981503instance ToJSON Version where
14991504 toJSON = toJSON . showVersion
15001505 {-# INLINE toJSON #-}
@@ -1502,6 +1507,9 @@ instance ToJSON Version where
15021507 toEncoding = toEncoding . showVersion
15031508 {-# INLINE toEncoding #-}
15041509
1510+instance ToJSONKey Version where
1511+ toJSONKey = toJSONKeyText (T.pack . showVersion)
1512+
15051513-------------------------------------------------------------------------------
15061514-- semigroups NonEmpty
15071515-------------------------------------------------------------------------------
@@ -1552,6 +1560,79 @@ instance (ToJSON a) => ToJSON (DList.DList a) where
15521560 toEncoding = toEncoding1
15531561 {-# INLINE toEncoding #-}
15541562
1563+-------------------------------------------------------------------------------
1564+-- transformers - Functors
1565+-------------------------------------------------------------------------------
1566+
1567+instance ToJSON1 Identity where
1568+ liftToJSON t _ (Identity a) = t a
1569+ {-# INLINE liftToJSON #-}
1570+
1571+ liftToJSONList _ tl xs = tl (map runIdentity xs)
1572+ {-# INLINE liftToJSONList #-}
1573+
1574+ liftToEncoding t _ (Identity a) = t a
1575+ {-# INLINE liftToEncoding #-}
1576+
1577+ liftToEncodingList _ tl xs = tl (map runIdentity xs)
1578+ {-# INLINE liftToEncodingList #-}
1579+
1580+instance (ToJSON a) => ToJSON (Identity a) where
1581+ toJSON = toJSON1
1582+ {-# INLINE toJSON #-}
1583+
1584+ toJSONList = liftToJSONList toJSON toJSONList
1585+ {-# INLINE toJSONList #-}
1586+
1587+ toEncoding = toEncoding1
1588+ {-# INLINE toEncoding #-}
1589+
1590+ toEncodingList = liftToEncodingList toEncoding toEncodingList
1591+ {-# INLINE toEncodingList #-}
1592+
1593+instance (ToJSONKey a, ToJSON a) => ToJSONKey (Identity a) where
1594+ toJSONKey = contramapToJSONKeyFunction runIdentity toJSONKey
1595+ toJSONKeyList = contramapToJSONKeyFunction (map runIdentity) toJSONKeyList
1596+
1597+
1598+instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Compose f g) where
1599+ liftToJSON tv tvl (Compose x) = liftToJSON g gl x
1600+ where
1601+ g = liftToJSON tv tvl
1602+ gl = liftToJSONList tv tvl
1603+ {-# INLINE liftToJSON #-}
1604+
1605+ liftToJSONList te tel xs = liftToJSONList g gl (map getCompose xs)
1606+ where
1607+ g = liftToJSON te tel
1608+ gl = liftToJSONList te tel
1609+ {-# INLINE liftToJSONList #-}
1610+
1611+ liftToEncoding te tel (Compose x) = liftToEncoding g gl x
1612+ where
1613+ g = liftToEncoding te tel
1614+ gl = liftToEncodingList te tel
1615+ {-# INLINE liftToEncoding #-}
1616+
1617+ liftToEncodingList te tel xs = liftToEncodingList g gl (map getCompose xs)
1618+ where
1619+ g = liftToEncoding te tel
1620+ gl = liftToEncodingList te tel
1621+ {-# INLINE liftToEncodingList #-}
1622+
1623+instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Compose f g a) where
1624+ toJSON = toJSON1
1625+ {-# INLINE toJSON #-}
1626+
1627+ toJSONList = liftToJSONList toJSON toJSONList
1628+ {-# INLINE toJSONList #-}
1629+
1630+ toEncoding = toEncoding1
1631+ {-# INLINE toEncoding #-}
1632+
1633+ toEncodingList = liftToEncodingList toEncoding toEncodingList
1634+ {-# INLINE toEncodingList #-}
1635+
15551636-------------------------------------------------------------------------------
15561637-- containers
15571638-------------------------------------------------------------------------------
@@ -1617,14 +1698,14 @@ instance ToJSON a => ToJSON (IntMap.IntMap a) where
16171698
16181699instance ToJSONKey k => ToJSON1 (M.Map k) where
16191700 liftToJSON g _ = case toJSONKey of
1620− ToJSONKeyText (f,_) -> Object . mapHashKeyVal f g
1621− ToJSONKeyValue (f,_) -> Array . V.fromList . map (toJSONPair f g) . M.toList
1701+ ToJSONKeyText f _ -> Object . mapHashKeyVal f g
1702+ ToJSONKeyValue f _ -> Array . V.fromList . map (toJSONPair f g) . M.toList
16221703 {-# INLINE liftToJSON #-}
16231704
16241705 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> M.Map k a -> Encoding
16251706 liftToEncoding g _ = case toJSONKey of
1626− ToJSONKeyText (_,f) -> dict f g M.foldrWithKey
1627− ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . M.toList
1707+ ToJSONKeyText _ f -> dict f g M.foldrWithKey
1708+ ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . M.toList
16281709 where
16291710 -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
16301711 pairEncoding f (a, b) = tuple $ f a >*< g b
@@ -1736,14 +1817,14 @@ instance (ToJSON a) => ToJSON (HashSet.HashSet a) where
17361817
17371818instance ToJSONKey k => ToJSON1 (H.HashMap k) where
17381819 liftToJSON g _ = case toJSONKey of
1739− ToJSONKeyText (f,_) -> Object . mapKeyVal f g
1740− ToJSONKeyValue (f,_) -> Array . V.fromList . map (toJSONPair f g) . H.toList
1820+ ToJSONKeyText f _ -> Object . mapKeyVal f g
1821+ ToJSONKeyValue f _ -> Array . V.fromList . map (toJSONPair f g) . H.toList
17411822 {-# INLINE liftToJSON #-}
17421823
17431824 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> H.HashMap k a -> Encoding
17441825 liftToEncoding g _ = case toJSONKey of
1745− ToJSONKeyText (_,f) -> dict f g H.foldrWithKey
1746− ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . H.toList
1826+ ToJSONKeyText _ f -> dict f g H.foldrWithKey
1827+ ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . H.toList
17471828 where
17481829 -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
17491830 pairEncoding f (a, b) = tuple $ f a >*< g b
@@ -1823,13 +1904,12 @@ instance ToJSONKey UTCTime where
18231904 toJSONKey = toJSONKeyTextEnc E.utcTime
18241905
18251906-- | Encode something t a JSON string.
1826−stringEncoding :: Encoding -> Value
1907+stringEncoding :: Encoding' Text -> Value
18271908stringEncoding = String
18281909 . T.dropAround (== '"')
18291910 . T.decodeLatin1
18301911 . L.toStrict
1831− . B.toLazyByteString
1832− . fromEncoding
1912+ . E.encodingToLazyByteString
18331913{-# INLINE stringEncoding #-}
18341914
18351915instance ToJSON NominalDiffTime where
@@ -1922,29 +2002,17 @@ instance ToJSONKey b => ToJSONKey (Tagged a b) where
19222002-- Instances for converting t map keys
19232003-------------------------------------------------------------------------------
19242004
1925−-- | TODO: Move ToJSONKEyFunction to .Types(.Internal),
1926−-- export and document this function from there
1927−toJSONKeyTextEnc :: (a -> Encoding) -> ToJSONKeyFunction a
1928−toJSONKeyTextEnc e = ToJSONKeyText
1929− -- TODO: dropAround is also used in stringEncoding, which is unfortunate atm
1930− ( T.dropAround (== '"') . T.decodeLatin1 . L.toStrict . B.toLazyByteString . fromEncoding . e
1931− , e
1932− )
1933−
19342005instance (ToJSON a, ToJSON b) => ToJSONKey (a,b)
19352006instance (ToJSON a, ToJSON b, ToJSON c) => ToJSONKey (a,b,c)
19362007instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSONKey (a,b,c,d)
19372008
19382009instance ToJSONKey Char where
1939− toJSONKey = ToJSONKeyText (T.singleton, toEncoding)
1940− toJSONKeyList = ToJSONKeyText (T.pack, toEncoding . T.pack)
2010+ toJSONKey = ToJSONKeyText T.singleton (E.string . (:[]))
2011+ toJSONKeyList = toJSONKeyText T.pack
19412012
19422013instance (ToJSONKey a, ToJSON a) => ToJSONKey [a] where
19432014 toJSONKey = toJSONKeyList
19442015
1945−instance (ToJSONKey a, ToJSON a) => ToJSONKey (Identity a) where
1946− toJSONKey = contramapToJSONKeyFunction runIdentity toJSONKey
1947−
19482016-------------------------------------------------------------------------------
19492017-- Tuple instances, see tuple-instances-to.hs
19502018-------------------------------------------------------------------------------