Changed most ToJSON instances to use a new operator
This may help with readability.
I made some small other changes as well, mostly just linting hints.
I took a look at it, and it might be better to just alias the type instead of introducing toKey. Since both Key.Key and T.Text have IsString instances, no changes to other parts of the code is necessary. Or maybe keep both toKey and the alias?
Here's a patch of what I mean (I didn't know how to submit a PR to a PR? or however it works):
diff --git discord-haskell.cabal discord-haskell.cabal
index d5fd220..a0e74dd 100644
--- discord-haskell.cabal
+++ discord-haskell.cabal
@@ -89,7 +89,7 @@ library
, Discord.Internal.Types.ScheduledEvents
build-depends:
base ==4.*,
- aeson >=1.5 && <1.6,
+ aeson >= 1.5 && < 1.6 || >= 2.0 && < 2.2,
async >=2.2 && <2.3,
bytestring >=0.10 && <0.11,
base64-bytestring >=1.1 && <1.2,
diff --git src/Discord/Internal/Rest/Webhook.hs src/Discord/Internal/Rest/Webhook.hs
index ad4b419..7b4a545 100644
--- src/Discord/Internal/Rest/Webhook.hs
+++ src/Discord/Internal/Rest/Webhook.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RecordWildCards #-}
@@ -25,18 +24,6 @@ import Network.HTTP.Client.MultipartFormData (partBS, partFileRequestBody)
import Discord.Internal.Rest.Prelude
import Discord.Internal.Types
--- aeson introduced type name for json key (text)
--- https://github.com/haskell/aeson/issues/881
--- this is unneeded due to version bounds.
--- # if MIN_VERSION_aeson(2, 0, 0)
--- import qualified Data.Aeson.Key as Key
--- toKey :: T.Text -> Key.Key
--- toKey = Key.fromText
--- # else
--- toKey :: T.Text -> T.Text
--- toKey = id
--- # endif
-
instance Request (WebhookRequest a) where
majorRoute = webhookMajorRoute
jsonRequest = webhookJsonRequest
@@ -137,7 +124,7 @@ data WebhookContent = WebhookContentText T.Text
| WebhookContentEmbeds [CreateEmbed]
deriving (Show, Read, Eq, Ord)
-webhookContentJson :: WebhookContent -> [(T.Text, Value)]
+webhookContentJson :: WebhookContent -> [(AesonKey, Value)]
webhookContentJson c = case c of
WebhookContentText t -> [("content", toJSON t)]
WebhookContentFile _ _ -> []
diff --git src/Discord/Internal/Types/Prelude.hs src/Discord/Internal/Types/Prelude.hs
index 4f0b491..20c163e 100644
--- src/Discord/Internal/Types/Prelude.hs
+++ src/Discord/Internal/Types/Prelude.hs
@@ -3,6 +3,7 @@
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE CPP #-}
-- | Provides base types and utility functions needed for modules in Discord.Internal.Types
module Discord.Internal.Types.Prelude
@@ -45,6 +46,7 @@ module Discord.Internal.Types.Prelude
, (.==)
, (.=?)
+ , AesonKey
, objectFromMaybes
)
@@ -65,6 +67,10 @@ import Web.Internal.HttpApiData
import qualified Data.ByteString as B
import qualified Data.Text as T
+#if MIN_VERSION_aeson(2, 0, 0)
+import qualified Data.Aeson.Key as Key
+#endif
+
-- | Authorization token for the Discord API
newtype Auth = Auth T.Text
deriving (Show, Read, Eq, Ord)
@@ -241,12 +247,21 @@ class Data a => InternalDiscordEnum a where
| fromIntegral (round i) == i = Just $ round i
| otherwise = Nothing
--- when we upgrade aeson, we need to change Text to Key
-
-(.==) :: ToJSON a => T.Text -> a -> Maybe Pair
+-- Aeson 2.0 uses KeyMaps with a defined Key type for its objects. Aeson up to
+-- 1.5 uses HashMaps with Text for the key. Both types have an IsString instance.
+-- To keep our version bounds as loose as possible while the Haskell ecosystem
+-- (and thus our users) switch over to Aeson 2.0, we use some CPP to define a
+-- AesonKey as an alias.
+#if MIN_VERSION_aeson(2, 0, 0)
+type AesonKey = Key.Key
+# else
+type AesonKey = T.Text
+# endif
+
+(.==) :: ToJSON a => AesonKey -> a -> Maybe Pair
k .== v = Just (k .= v)
-(.=?) :: ToJSON a => T.Text -> Maybe a -> Maybe Pair
+(.=?) :: ToJSON a => AesonKey -> Maybe a -> Maybe Pair
k .=? (Just v) = Just (k .= v)
_ .=? Nothing = Nothing
I think yutotakano's suggestion is the right call, as it allows potential support for both Aeson 1.x and 2.x with next to no change to user code (I think in most cases the only change needed would be to bump the Aeson version in cabal/stack/whatever dependency manager the user uses)
You can submit a PR to my repo which can then get merged in here, but that seems messy; I'm gonna apply that patch soon.
Looks great!
Goal is to get this and https://github.com/discord-haskell/discord-haskell/pull/135 into a 1.15 release
I have a long day ahead, should get around to the release process late tonight