diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
 
 `hslua-aeson` uses [PVP Versioning][].
 
+## hslua-aeson-2.3.2
+
+Released 2026-01-08.
+
+-   Dropped support for aeson < 2.0.3.
+
 ## hslua-aeson-2.3.1.1
 
 Released 2024-07-09.
diff --git a/hslua-aeson.cabal b/hslua-aeson.cabal
--- a/hslua-aeson.cabal
+++ b/hslua-aeson.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                hslua-aeson
-version:             2.3.1.1
+version:             2.3.2
 synopsis:            Allow aeson data types to be used with Lua.
 description:         This package provides instances to push and receive any
                      datatype encodable as JSON to and from the Lua stack.
@@ -9,20 +9,14 @@
 license-file:        LICENSE
 author:              Albert Krewinkel
 maintainer:          Albert Krewinkel <tarleb@hslua.org>
-copyright:           © 2017–2024 Albert Krewinkel
+copyright:           © 2017-2026 Albert Krewinkel
 category:            Foreign
 extra-source-files:  README.md
                    , CHANGELOG.md
-tested-with:         GHC == 8.4.4
-                   , GHC == 8.6.5
-                   , GHC == 8.8.4
-                   , GHC == 8.10.7
-                   , GHC == 9.0.2
-                   , GHC == 9.2.8
-                   , GHC == 9.4.8
-                   , GHC == 9.6.5
-                   , GHC == 9.8.2
-                   , GHC == 9.10.1
+tested-with:         GHC == 9.6
+                   , GHC == 9.8
+                   , GHC == 9.10
+                   , GHC == 9.12
 
 source-repository head
   type:                git
@@ -32,40 +26,35 @@
 common common-options
   default-language:    Haskell2010
   build-depends:       base                 >= 4.11   && < 5
-                     , aeson                >= 1.5    && < 2.3
-                     , bytestring           >= 0.10.2 && < 0.13
-                     , containers           >= 0.5.9  && < 0.8
-                     , hashable             >= 1.2    && < 1.6
+                     , aeson                >= 2.0.3  && < 2.3
                      , hslua-core           >= 2.0    && < 2.4
                      , hslua-marshalling    >= 2.1    && < 2.4
-                     , mtl                  >= 2.2    && < 2.4
                      , scientific           >= 0.3    && < 0.4
-                     , unordered-containers >= 0.2    && < 0.3
-                     , text                 >= 1.2    && < 2.2
-                     , vector               >= 0.7
+                     , vector               >= 0.7    && < 0.14
   default-extensions:  BangPatterns
-                     , CPP
                      , LambdaCase
                      , OverloadedStrings
                      , TypeApplications
   ghc-options:         -Wall
+                       -Wcpp-undef
+                       -Werror=missing-home-modules
+                       -Widentities
                        -Wincomplete-record-updates
+                       -Wincomplete-uni-patterns
                        -Wnoncanonical-monad-instances
+                       -Wpartial-fields
                        -Wredundant-constraints
-  if impl(ghc >= 8.2)
-    ghc-options:         -Wcpp-undef
-                         -Werror=missing-home-modules
-  if impl(ghc >= 8.4)
-    ghc-options:         -Widentities
-                         -Wincomplete-uni-patterns
-                         -Wpartial-fields
-                         -fhide-source-paths
+                       -fhide-source-paths
+  if impl(ghc >= 8.10)
+    ghc-options:         -Wunused-packages
+  if impl(ghc >= 9.0)
+    ghc-options:         -Winvalid-haddock
 
 library
   import:              common-options
   exposed-modules:     HsLua.Aeson
   hs-source-dirs:      src
-  build-depends:       base                 >= 4.7    && < 5
+  build-depends:       bytestring           >= 0.10.2 && < 0.13
   default-language:    Haskell2010
 
 test-suite test-hslua-aeson
@@ -74,10 +63,12 @@
   main-is:             test-hslua-aeson.hs
   hs-source-dirs:      test
   build-depends:       hslua-aeson
+                     , aeson                >= 2.0.3  && < 2.3
                      , QuickCheck
                      , quickcheck-instances
                      , tasty                >= 0.11
                      , tasty-quickcheck     >= 0.8
                      , tasty-hunit          >= 0.10
+                     , text                 >= 1.2    && < 2.2
   ghc-options:         -threaded
   default-language:    Haskell2010
diff --git a/src/HsLua/Aeson.hs b/src/HsLua/Aeson.hs
--- a/src/HsLua/Aeson.hs
+++ b/src/HsLua/Aeson.hs
@@ -1,6 +1,6 @@
 {-|
 Module      :  HsLua.Aeson
-Copyright   :  © 2017-2024 Albert Krewinkel
+Copyright   :  © 2017-2026 Albert Krewinkel
 License     :  MIT
 Maintainer  :  Albert Krewinkel <tarleb@hslua.org>
 
@@ -34,27 +34,17 @@
 
 import Control.Applicative ((<|>))
 import Control.Monad ((<$!>), void)
+import Data.Aeson.Key (toText, fromText)
 import Data.Scientific (toRealFloat, fromFloatDigits)
 import Foreign.Ptr (nullPtr)
 import HsLua.Core as Lua
 import HsLua.Marshalling as Lua
 
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.KeyMap as KeyMap
 import qualified Data.ByteString as B
 import qualified Data.Vector as Vector
 import qualified HsLua.Core.Utf8 as UTF8
-
-#if MIN_VERSION_aeson(2,0,0)
-import Data.Aeson.Key (toText, fromText)
-import qualified Data.Aeson.KeyMap as KeyMap
-#else
-import Data.Text (Text)
-import qualified Data.HashMap.Strict as KeyMap
-
-toText, fromText :: Text -> Text
-toText = id
-fromText = id
-#endif
 
 -- | Hslua StackValue instance for the Aeson Value data type.
 pushValue :: LuaError e => Pusher e Aeson.Value
diff --git a/test/test-hslua-aeson.hs b/test/test-hslua-aeson.hs
--- a/test/test-hslua-aeson.hs
+++ b/test/test-hslua-aeson.hs
@@ -1,6 +1,6 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {-|
-Copyright   :  © 2017-2024 Albert Krewinkel
+Copyright   :  © 2017-2026 Albert Krewinkel
 License     :  MIT
 
 Tests for Aeson–Lua glue.
@@ -19,19 +19,10 @@
 import Test.QuickCheck.Instances ()
 
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.KeyMap as KeyMap
 import qualified Data.Vector as Vector
 import qualified Test.QuickCheck.Monadic as QC
 
-#if MIN_VERSION_aeson(2,0,0)
-import qualified Data.Aeson.KeyMap as KeyMap
-#if !MIN_VERSION_aeson(2,0,3)
-import Data.Aeson.Key (Key, fromText)
-#endif
-#else
-import qualified Data.HashMap.Strict as KeyMap
-#endif
-
-
 -- | Run this spec.
 main :: IO ()
 main = defaultMain tests
@@ -131,34 +122,6 @@
 -- numbers.
 luaNumberToScientific :: Lua.Number -> Scientific
 luaNumberToScientific = fromFloatDigits . (realToFrac :: Lua.Number -> Double)
-
--- aeson defines instances for Arbitrary since 2.0.3.0
-#if !MIN_VERSION_aeson(2,0,3)
-instance Arbitrary Aeson.Value where
-  arbitrary = arbitraryValue 9
-
-#if MIN_VERSION_aeson(2,0,0)
-instance Arbitrary Key where
-  arbitrary = fmap fromText arbitrary
-
-instance Arbitrary a => Arbitrary (KeyMap.KeyMap a) where
-  arbitrary = fmap KeyMap.fromList arbitrary
-#endif
-
-arbitraryValue :: Int -> Gen Aeson.Value
-arbitraryValue size = frequency
-    [ (1, return Aeson.Null)
-    , (4, Aeson.Bool <$> arbitrary)
-    -- Note: we don't draw numbers from the whole possible range, but
-    -- only from the range of numbers that Lua can handle without
-    -- rounding errors. This is ok, as JSON doesn't define a required
-    -- precision, and (usually) matches the behavior of JavaScript.
-    , (4, Aeson.Number . luaNumberToScientific . Lua.Number <$> arbitrary)
-    , (4, Aeson.String <$> arbitrary)
-    , (2, resize (size - 1) $ Aeson.Array <$> arbitrary)
-    , (2, resize (size - 1) $ Aeson.Object <$> arbitrary)
-    ]
-#endif
 
 --
 -- Type for __toaeson tests
