diff --git a/aws-cloudfront-signed-cookies.cabal b/aws-cloudfront-signed-cookies.cabal
--- a/aws-cloudfront-signed-cookies.cabal
+++ b/aws-cloudfront-signed-cookies.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name: aws-cloudfront-signed-cookies
-version: 0.2.0.8
+version: 0.2.0.9
 
 synopsis: Generate signed cookies for AWS CloudFront
 category: Network, AWS, Cloud
@@ -58,6 +58,7 @@
       aeson
            ^>= 1.4
         || ^>= 1.5
+        || ^>= 2.0
     , aeson-pretty
            ^>= 0.8
     , asn1-encoding
@@ -107,8 +108,6 @@
     , time
            ^>= 1.8
         || ^>= 1.9
-    , unordered-containers
-           ^>= 0.2.10
     , vector
            ^>= 0.12.0.1
 
@@ -131,7 +130,7 @@
   default-language: Haskell2010
   hs-source-dirs: test
   type: exitcode-stdio-1.0
-  main-is: hedgehog.hs
+  main-is: Main.hs
   ghc-options: -threaded
   build-depends:
       aws-cloudfront-signed-cookies
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -22,7 +22,13 @@
 
 - Support GHC 8.10
 
-## 0.2.0.8 - ?
+## 0.2.0.8 - 2021-06-10
 
 - Add proper version bounds for all dependencies
 - Support GHC 9.0
+
+## 0.2.0.9 - 2021-11-15
+
+- Support Aeson 2.0
+- Remove unordered-containers dependency
+- [Fix test suite on macos](https://github.com/typeclasses/aws-cloudfront-signed-cookies/issues/2)
diff --git a/library/Network/AWS/CloudFront/SignedCookies/Policy.hs b/library/Network/AWS/CloudFront/SignedCookies/Policy.hs
--- a/library/Network/AWS/CloudFront/SignedCookies/Policy.hs
+++ b/library/Network/AWS/CloudFront/SignedCookies/Policy.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, TypeApplications #-}
 
 module Network.AWS.CloudFront.SignedCookies.Policy
   (
@@ -23,7 +23,9 @@
 import Network.AWS.CloudFront.SignedCookies.Types
 
 -- aeson
-import qualified Data.Aeson as A
+import qualified Data.Aeson as A (Value, eitherDecode', encode, object)
+import qualified Data.Aeson.Types as A (Pair)
+import Data.Aeson ((.=), toJSON)
 
 -- base
 import Control.Monad ((>=>))
@@ -44,9 +46,6 @@
 -- time
 import Data.Time.Clock.POSIX (getPOSIXTime)
 
--- unordered-containers
-import qualified Data.HashMap.Strict as Map
-
 -- vector
 import qualified Data.Vector as Vec
 
@@ -65,44 +64,42 @@
   LBS.toStrict . A.encode . policyValue
 
 policyValue :: Policy -> A.Value
-policyValue policy =
-  A.Object $ Map.singleton "Statement" $
-    A.Array $ Vec.singleton $
-      A.Object $ "Resource" .= resourceValue policy <>
-                 "Condition" .= conditionValue policy
+policyValue policy = A.object [ "Statement" .= statement ]
+  where
+    statement = toJSON @[A.Value]
+      [ A.object
+        [ "Resource" .= resourceValue policy
+        , "Condition" .= conditionValue policy
+        ]
+      ]
 
 resourceValue :: Policy -> A.Value
-resourceValue (Policy (Resource x) _ _ _) = A.String x
+resourceValue (Policy (Resource x) _ _ _) = toJSON @Text x
 
 conditionValue :: Policy -> A.Value
 conditionValue (Policy _ start end ip) =
-  A.Object $ startCondition <> endCondition <> ipCondition
+  A.object $ startCondition <> endCondition <> ipCondition
   where
 
-    startCondition :: A.Object =
+    startCondition :: [A.Pair] =
       case start of
-        StartImmediately -> mempty
-        StartTime x -> "DateGreaterThan" .= posixTimeValue x
+        StartImmediately -> []
+        StartTime x -> ["DateGreaterThan" .= posixTimeValue x]
 
-    endCondition :: A.Object =
+    endCondition :: [A.Pair] =
       case end of
-        EndTime x -> "DateLessThan" .= posixTimeValue x
+        EndTime x -> ["DateLessThan" .= posixTimeValue x]
 
-    ipCondition :: A.Object =
+    ipCondition :: [A.Pair] =
       case ip of
-        AnyIp -> mempty
-        IpAddress x -> "IpAddress" .= sourceIpValue x
+        AnyIp -> []
+        IpAddress x -> ["IpAddress" .= sourceIpValue x]
 
 posixTimeValue :: POSIXTime -> A.Value
-posixTimeValue =
-  A.Object . ("AWS:EpochTime" .=) . A.Number . fromInteger . round
+posixTimeValue x = A.object ["AWS:EpochTime" .= toJSON @Integer (round x) ]
 
 sourceIpValue :: Text -> A.Value
-sourceIpValue =
-  A.Object . ("AWS:SourceIp" .=) . A.String
-
-(.=) :: Text -> A.Value -> A.Object
-(.=) = Map.singleton
+sourceIpValue x = A.object ["AWS:SourceIp" .= toJSON @Text x]
 
 jsonTextPolicy :: Text -> Either String Policy
 jsonTextPolicy =
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE OverloadedStrings, QuasiQuotes, TemplateHaskell #-}
+
+module Main (main) where
+
+import Network.AWS.CloudFront.SignedCookies
+
+-- base
+import Control.Monad (unless)
+import Data.Either (isLeft)
+import Data.Foldable (for_)
+import qualified System.Exit as Exit
+import qualified System.IO   as IO
+
+-- hedgehog
+import           Hedgehog
+import qualified Hedgehog.Gen as Gen
+import qualified Hedgehog.Range as Range
+
+-- neat-interpolation
+import NeatInterpolation
+
+main :: IO ()
+main = do
+  for_ [IO.stdout, IO.stderr] $ \h -> do
+    IO.hSetEncoding h IO.utf8
+    IO.hSetBuffering h IO.LineBuffering
+  success <- Hedgehog.checkParallel $$(Hedgehog.discover)
+  unless success Exit.exitFailure
+
+prop_jsonPolicy_1 :: Property
+prop_jsonPolicy_1 = withTests 1 $ property $
+  let
+    x = [text|
+        {
+          "Statement": [
+              {
+                 "Resource": "http://d111111abcdef8.cloudfront.net/game_download.zip",
+                 "Condition": {
+                    "IpAddress": {"AWS:SourceIp": "192.0.2.0/24"},
+                    "DateLessThan": {"AWS:EpochTime": 1357034400}
+                 }
+              }
+           ]
+        }
+      |]
+
+    p = Policy
+      (Resource "http://d111111abcdef8.cloudfront.net/game_download.zip")
+      StartImmediately
+      (EndTime 1357034400)
+      (IpAddress "192.0.2.0/24")
+  in
+    jsonTextPolicy x === Right p
+
+prop_jsonPolicy_2 :: Property
+prop_jsonPolicy_2 = withTests 1 $ property $
+  let
+    x = [text|
+        {
+           "Statement": [
+              {
+                 "Resource": "http://*",
+                 "Condition": {
+                    "IpAddress": {"AWS:SourceIp": "192.0.2.10/32"},
+                    "DateGreaterThan": {"AWS:EpochTime": 1357034400},
+                    "DateLessThan": {"AWS:EpochTime": 1357120800}
+                 }
+              }
+           ]
+        }
+      |]
+
+    p = Policy
+      (Resource "http://*")
+      (StartTime 1357034400)
+      (EndTime 1357120800)
+      (IpAddress "192.0.2.10/32")
+  in
+    jsonTextPolicy x === Right p
+
+prop_jsonPolicy_3 :: Property
+prop_jsonPolicy_3 = withTests 1 $ property $
+  let
+    x = [text|
+        {
+           "Statement": [
+              {
+                 "Resource": "http://*",
+                 "Condition": {
+                    "IpAddress": {"AWS:SourceIp": "192.0.2.10/32"},
+                    "DateGreaterThan":
+      |]
+
+  in
+    assert (isLeft (jsonTextPolicy x))
diff --git a/test/hedgehog.hs b/test/hedgehog.hs
deleted file mode 100644
--- a/test/hedgehog.hs
+++ /dev/null
@@ -1,95 +0,0 @@
-{-# LANGUAGE OverloadedStrings, QuasiQuotes, TemplateHaskell #-}
-
-module Main (main) where
-
-import Network.AWS.CloudFront.SignedCookies
-
--- base
-import Control.Monad (unless)
-import Data.Either (isLeft)
-import Data.Foldable (for_)
-import qualified System.Exit as Exit
-import qualified System.IO   as IO
-
--- hedgehog
-import           Hedgehog
-import qualified Hedgehog.Gen as Gen
-import qualified Hedgehog.Range as Range
-
--- neat-interpolation
-import NeatInterpolation
-
-main :: IO ()
-main = do
-  for_ [IO.stdout, IO.stderr] $ \h -> do
-    IO.hSetEncoding h IO.utf8
-    IO.hSetBuffering h IO.LineBuffering
-  success <- Hedgehog.checkParallel $$(Hedgehog.discover)
-  unless success Exit.exitFailure
-
-prop_jsonPolicy_1 :: Property
-prop_jsonPolicy_1 = withTests 1 $ property $
-  let
-    x = [text|
-        {
-          "Statement": [
-              {
-                 "Resource": "http://d111111abcdef8.cloudfront.net/game_download.zip",
-                 "Condition": {
-                    "IpAddress": {"AWS:SourceIp": "192.0.2.0/24"},
-                    "DateLessThan": {"AWS:EpochTime": 1357034400}
-                 }
-              }
-           ]
-        }
-      |]
-
-    p = Policy
-      (Resource "http://d111111abcdef8.cloudfront.net/game_download.zip")
-      StartImmediately
-      (EndTime 1357034400)
-      (IpAddress "192.0.2.0/24")
-  in
-    jsonTextPolicy x === Right p
-
-prop_jsonPolicy_2 :: Property
-prop_jsonPolicy_2 = withTests 1 $ property $
-  let
-    x = [text|
-        {
-           "Statement": [
-              {
-                 "Resource": "http://*",
-                 "Condition": {
-                    "IpAddress": {"AWS:SourceIp": "192.0.2.10/32"},
-                    "DateGreaterThan": {"AWS:EpochTime": 1357034400},
-                    "DateLessThan": {"AWS:EpochTime": 1357120800}
-                 }
-              }
-           ]
-        }
-      |]
-
-    p = Policy
-      (Resource "http://*")
-      (StartTime 1357034400)
-      (EndTime 1357120800)
-      (IpAddress "192.0.2.10/32")
-  in
-    jsonTextPolicy x === Right p
-
-prop_jsonPolicy_3 :: Property
-prop_jsonPolicy_3 = withTests 1 $ property $
-  let
-    x = [text|
-        {
-           "Statement": [
-              {
-                 "Resource": "http://*",
-                 "Condition": {
-                    "IpAddress": {"AWS:SourceIp": "192.0.2.10/32"},
-                    "DateGreaterThan":
-      |]
-
-  in
-    assert (isLeft (jsonTextPolicy x))
