diff --git a/hw-aeson.cabal b/hw-aeson.cabal
--- a/hw-aeson.cabal
+++ b/hw-aeson.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name:                   hw-aeson
-version:                0.1.6.0
+version:                0.1.7.0
 synopsis:               Convenience functions for Aeson
 description:            Convenience functions for Aeson.
 category:               Data, JSON
@@ -23,9 +23,11 @@
 common base                       { build-depends: base                       >= 4.11       && < 5      }
 
 common aeson                      { build-depends: aeson                      >= 1.4        && < 2.1    }
-common containers                 { build-depends: containers                 >= 0.6        && < 0.7   }
+common bytestring                 { build-depends: bytestring                 >= 0.10       && < 0.12   }
+common containers                 { build-depends: containers                 >= 0.6        && < 0.7    }
 common doctest                    { build-depends: doctest                    >= 0.16.2     && < 0.21   }
 common doctest-discover           { build-depends: doctest-discover           >= 0.2        && < 0.3    }
+common hashable                   { build-depends: hashable                   >= 1.3        && < 1.5    }
 common hedgehog                   { build-depends: hedgehog                   >= 0.6        && < 1.3    }
 common hspec                      { build-depends: hspec                      >= 2.4        && < 3      }
 common text                       { build-depends: text                       >= 1.2        && < 1.3    }
@@ -40,7 +42,9 @@
 library
   import:               base, config
                       , aeson
+                      , bytestring
                       , containers
+                      , hashable
                       , text
                       , text-short
                       , unordered-containers
@@ -51,6 +55,8 @@
   exposed-modules:      HaskellWorks.Data.Aeson
                         HaskellWorks.Data.Aeson.Compat
                         HaskellWorks.Data.Aeson.Compat.Map
+                        HaskellWorks.Data.Aeson.Compat.Map.V1
+                        HaskellWorks.Data.Aeson.Compat.Map.V2
 
 test-suite hw-aeson-test
   import:               base, config
diff --git a/src/HaskellWorks/Data/Aeson.hs b/src/HaskellWorks/Data/Aeson.hs
--- a/src/HaskellWorks/Data/Aeson.hs
+++ b/src/HaskellWorks/Data/Aeson.hs
@@ -13,11 +13,15 @@
 
 import Data.Aeson (pairs, object, KeyValue((.=)), ToJSON(toJSON, toEncoding), Series, Value(Null))
 import Data.Aeson.Encoding (Encoding)
-import Data.Aeson.Types (Pair, Parser)
+import Data.Aeson.Types (Pair, Parser, parseEither)
 import Data.Monoid (Endo(..))
 import HaskellWorks.Data.Aeson.Compat (Key)
 import Text.Read (readMaybe)
 
+import qualified Data.Aeson           as J
+import qualified Data.Aeson.Types     as J
+import qualified Data.ByteString.Lazy as LBS
+
 infixr 7 .?=
 infixr 7 .!=
 
@@ -96,3 +100,6 @@
 instance ToJsonKeyValues a => ToJSON (WithJsonKeyValues a) where
   toJSON = objectEndo . toJsonKeyValues . unWithJsonKeyValues
   toEncoding = pairs . mconcat . toJsonKeyValues . unWithJsonKeyValues
+
+eitherDecodeWith :: (Value -> Parser a) -> LBS.ByteString -> Either String a
+eitherDecodeWith f lbs = J.eitherDecode lbs >>= J.parseEither f
diff --git a/src/HaskellWorks/Data/Aeson/Compat/Map.hs b/src/HaskellWorks/Data/Aeson/Compat/Map.hs
--- a/src/HaskellWorks/Data/Aeson/Compat/Map.hs
+++ b/src/HaskellWorks/Data/Aeson/Compat/Map.hs
@@ -2,49 +2,10 @@
 
 module HaskellWorks.Data.Aeson.Compat.Map
   ( module JM
-  , KeyMap(..)
-  , foldlWithKey'
-  , fromHashMapText
-  , toHashMapText
   ) where
 
-import qualified Data.Map as M
-import qualified HaskellWorks.Data.Aeson.Compat as J
-
-import Data.HashMap.Strict (HashMap)
-import Data.Text (Text)
-
 #if MIN_VERSION_aeson(2,0,0)
-import qualified Data.Aeson.KeyMap as JM
-import Data.Aeson.KeyMap (KeyMap)
-#else
-import qualified Data.HashMap.Strict as JM
-import Data.HashMap.Strict hiding (foldlWithKey')
-#endif
-
-#if !MIN_VERSION_aeson(2,0,0)
-type KeyMap v = JM.HashMap Text v
-#endif
-
-foldlWithKey' :: (a -> J.Key -> b -> a) -> a -> KeyMap b -> a
-#if MIN_VERSION_aeson(2,0,0)
-foldlWithKey' f a = M.foldlWithKey' f a . JM.toMap
-#else
-foldlWithKey'= JM.foldlWithKey'
-#endif
-
-#if MIN_VERSION_aeson(2,0,0)
-fromHashMapText :: HashMap Text a ->  KeyMap a
-fromHashMapText = JM.fromHashMapText
-#else
-fromHashMapText :: HashMap Text a -> HashMap Text a
-fromHashMapText = id
-#endif
-
-#if MIN_VERSION_aeson(2,0,0)
-toHashMapText :: KeyMap a -> HashMap Text a
-toHashMapText = JM.toHashMapText
+import HaskellWorks.Data.Aeson.Compat.Map.V2 as JM
 #else
-toHashMapText :: HashMap Text a -> HashMap Text a
-toHashMapText = id
+import HaskellWorks.Data.Aeson.Compat.Map.V1 as JM
 #endif
diff --git a/src/HaskellWorks/Data/Aeson/Compat/Map/V1.hs b/src/HaskellWorks/Data/Aeson/Compat/Map/V1.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Aeson/Compat/Map/V1.hs
@@ -0,0 +1,198 @@
+module HaskellWorks.Data.Aeson.Compat.Map.V1
+  ( KeyMap
+  , Key
+  , foldlWithKey
+  , foldlWithKey'
+  , null
+  , lookup
+  , size
+  , member
+  , empty
+  , singleton
+  , insert
+  , delete
+  , alterF
+  , difference
+  , union
+  , unionWith
+  , unionWithKey
+  , intersection
+  , intersectionWith
+  , intersectionWithKey
+  , fromList
+  , fromListWith
+  , toList
+  , toAscList
+  , elems
+  , fromHashMap
+  , toHashMap
+  , fromHashMapText
+  , toHashMapText
+  , fromMap
+  , toMap
+  , fromMapText
+  , toMapText
+  , map
+  , mapWithKey
+  , traverseWithKey
+  , foldr
+  , foldr'
+  , foldl
+  , foldl'
+  , foldMapWithKey
+  , foldrWithKey
+  , keys
+  , filter
+  , filterWithKey
+  , mapMaybe
+  , mapMaybeWithKey
+  ) where
+
+import qualified Data.HashMap.Strict as HM
+import qualified Data.HashMap.Strict as HMS
+import qualified Data.Map as M
+import qualified HaskellWorks.Data.Aeson.Compat as J
+
+import Data.Hashable (Hashable)
+import Data.HashMap.Strict (HashMap)
+import Data.Map (Map)
+import Data.Text (Text)
+import Prelude hiding (filter, foldl, foldr, lookup, map, null)
+
+type KeyMap v = HM.HashMap Text v
+type Key = Text
+
+foldlWithKey :: (a -> Key -> b -> a) -> a -> KeyMap b -> a
+foldlWithKey = HM.foldlWithKey
+
+foldlWithKey' :: (a -> Key -> b -> a) -> a -> KeyMap b -> a
+foldlWithKey' = HM.foldlWithKey'
+
+null :: KeyMap v -> Bool
+null = HM.null
+
+lookup :: Key -> KeyMap v -> Maybe v
+lookup = HM.lookup
+
+size :: KeyMap v -> Int
+size = HM.size
+
+member :: Key -> KeyMap v -> Bool
+member = HM.member
+
+empty :: KeyMap v
+empty = HM.empty
+
+singleton :: Key -> v -> KeyMap v
+singleton = HM.singleton
+
+insert :: Key -> v -> KeyMap v -> KeyMap v
+insert = HM.insert
+
+delete :: Key -> KeyMap v -> KeyMap v
+delete = HM.delete
+
+alterF :: Functor f => (Maybe v -> f (Maybe v)) -> Key -> KeyMap v -> f (KeyMap v)
+alterF = HM.alterF
+
+difference :: KeyMap v -> KeyMap v' -> KeyMap v
+difference = HM.difference
+
+union :: KeyMap v -> KeyMap v -> KeyMap v
+union = HM.union
+
+unionWith :: (v -> v -> v) -> KeyMap v -> KeyMap v -> KeyMap v
+unionWith = HM.unionWith
+
+unionWithKey :: (Key -> v -> v -> v) -> KeyMap v -> KeyMap v -> KeyMap v
+unionWithKey = HM.unionWithKey
+
+intersection :: KeyMap a -> KeyMap b -> KeyMap a
+intersection = HM.intersection
+
+intersectionWith :: (a -> b -> c) -> KeyMap a -> KeyMap b -> KeyMap c
+intersectionWith = HM.intersectionWith
+
+intersectionWithKey :: (Key -> a -> b -> c) -> KeyMap a -> KeyMap b -> KeyMap c
+intersectionWithKey = HM.intersectionWithKey
+
+fromList :: [(Key, v)] -> KeyMap v
+fromList = HM.fromList
+
+fromListWith :: (v -> v -> v) -> [(Key, v)] -> KeyMap v
+fromListWith = HM.fromListWith
+
+toList :: KeyMap v -> [(Key, v)]
+toList = HM.toList
+
+toAscList :: KeyMap v -> [(Key, v)]
+toAscList = M.toList . toMap
+
+elems :: KeyMap v -> [v]
+elems = HM.elems
+
+fromHashMap :: HashMap Key v -> KeyMap v
+fromHashMap = id
+
+toHashMap :: KeyMap v -> HashMap Key v
+toHashMap = id
+
+fromHashMapText :: HashMap Text v -> KeyMap v
+fromHashMapText = id
+
+toHashMapText :: KeyMap v -> HashMap Text v
+toHashMapText = id
+
+fromMap :: Map Key v -> KeyMap v
+fromMap = HM.fromList . M.toList
+
+toMap :: KeyMap v -> Map Key v
+toMap = M.fromList . HM.toList
+
+fromMapText :: Map Text v -> KeyMap v
+fromMapText = fromMap
+
+toMapText :: KeyMap v -> Map Text v
+toMapText = toMap
+
+map :: (a -> b) -> KeyMap a -> KeyMap b
+map = HM.map
+
+mapWithKey :: (Key -> a -> b) -> KeyMap a -> KeyMap b
+mapWithKey = HM.mapWithKey
+
+traverseWithKey :: Applicative f => (Key -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
+traverseWithKey = HM.traverseWithKey
+
+foldr :: (a -> b -> b) -> b -> KeyMap a -> b
+foldr = HM.foldr
+
+foldr' :: (a -> b -> b) -> b -> KeyMap a -> b
+foldr' = HM.foldr'
+
+foldl :: (b -> a -> b) -> b -> KeyMap a -> b
+foldl = HM.foldl
+
+foldl' :: (b -> a -> b) -> b -> KeyMap a -> b
+foldl' = HM.foldl'
+
+foldMapWithKey :: Monoid m => (Key -> a -> m) -> KeyMap a -> m
+foldMapWithKey = HM.foldMapWithKey
+
+foldrWithKey :: (Key -> v -> a -> a) -> a -> KeyMap v -> a
+foldrWithKey = HM.foldrWithKey
+
+keys :: KeyMap v -> [Key]
+keys = HM.keys
+
+filter :: (v -> Bool) -> KeyMap v -> KeyMap v
+filter = HM.filter
+
+filterWithKey :: (Key -> v -> Bool) -> KeyMap v -> KeyMap v
+filterWithKey = HM.filterWithKey
+
+mapMaybe :: (a -> Maybe b) -> KeyMap a -> KeyMap b
+mapMaybe = HM.mapMaybe
+
+mapMaybeWithKey :: (Key -> v -> Maybe u) -> KeyMap v -> KeyMap u
+mapMaybeWithKey = HM.mapMaybeWithKey
diff --git a/src/HaskellWorks/Data/Aeson/Compat/Map/V2.hs b/src/HaskellWorks/Data/Aeson/Compat/Map/V2.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Aeson/Compat/Map/V2.hs
@@ -0,0 +1,206 @@
+{-# LANGUAGE CPP #-}
+
+module HaskellWorks.Data.Aeson.Compat.Map.V2
+  (
+#if MIN_VERSION_aeson(2,0,0)
+    KeyMap
+  , Key
+  , foldlWithKey
+  , foldlWithKey'
+  , null
+  , lookup
+  , size
+  , member
+  , empty
+  , singleton
+  , insert
+  , delete
+  , alterF
+  , difference
+  , union
+  , unionWith
+  , unionWithKey
+  , intersection
+  , intersectionWith
+  , intersectionWithKey
+  , fromList
+  , fromListWith
+  , toList
+  , toAscList
+  , elems
+  , fromHashMap
+  , toHashMap
+  , fromHashMapText
+  , toHashMapText
+  , fromMap
+  , toMap
+  , fromMapText
+  , toMapText
+  , map
+  , mapWithKey
+  , traverseWithKey
+  , foldr
+  , foldr'
+  , foldl
+  , foldl'
+  , foldMapWithKey
+  , foldrWithKey
+  , keys
+  , filter
+  , filterWithKey
+  , mapMaybe
+  , mapMaybeWithKey
+#endif
+  ) where
+
+#if MIN_VERSION_aeson(2,0,0)
+
+import qualified Data.Aeson.Key as K
+import qualified Data.Aeson.KeyMap as KM
+import qualified Data.Map as M
+import qualified HaskellWorks.Data.Aeson.Compat as J
+
+import Data.HashMap.Strict (HashMap)
+import Data.Map (Map)
+import Data.Text (Text)
+import Prelude hiding (filter, foldl, foldr, lookup, map, null)
+
+type KeyMap v = KM.KeyMap v
+type Key = J.Key
+
+foldlWithKey :: (a -> Key -> b -> a) -> a -> KeyMap b -> a
+foldlWithKey f a = M.foldlWithKey f a . KM.toMap
+
+foldlWithKey' :: (a -> Key -> b -> a) -> a -> KeyMap b -> a
+foldlWithKey' f a = M.foldlWithKey' f a . KM.toMap
+
+null :: KeyMap v -> Bool
+null = KM.null
+
+lookup :: Key -> KeyMap v -> Maybe v
+lookup = KM.lookup
+
+size :: KeyMap v -> Int
+size = KM.size
+
+member :: Key -> KeyMap v -> Bool
+member = KM.member
+
+empty :: KeyMap v
+empty = KM.empty
+
+singleton :: Key -> v -> KeyMap v
+singleton = KM.singleton
+
+insert :: Key -> v -> KeyMap v -> KeyMap v
+insert = KM.insert
+
+delete :: Key -> KeyMap v -> KeyMap v
+delete = KM.delete
+
+alterF :: Functor f => (Maybe v -> f (Maybe v)) -> Key -> KeyMap v -> f (KeyMap v)
+alterF = KM.alterF
+
+difference :: KeyMap v -> KeyMap v' -> KeyMap v
+difference = KM.difference
+
+union :: KeyMap v -> KeyMap v -> KeyMap v
+union = KM.union
+
+unionWith :: (v -> v -> v) -> KeyMap v -> KeyMap v -> KeyMap v
+unionWith = KM.unionWith
+
+unionWithKey :: (Key -> v -> v -> v) -> KeyMap v -> KeyMap v -> KeyMap v
+unionWithKey = KM.unionWithKey
+
+intersection :: KeyMap a -> KeyMap b -> KeyMap a
+intersection = KM.intersection
+
+intersectionWith :: (a -> b -> c) -> KeyMap a -> KeyMap b -> KeyMap c
+intersectionWith = KM.intersectionWith
+
+intersectionWithKey :: (Key -> a -> b -> c) -> KeyMap a -> KeyMap b -> KeyMap c
+intersectionWithKey = KM.intersectionWithKey
+
+fromList :: [(Key, v)] -> KeyMap v
+fromList = KM.fromList
+
+fromListWith :: (v -> v -> v) -> [(Key, v)] -> KeyMap v
+fromListWith = KM.fromListWith
+
+toList :: KeyMap v -> [(Key, v)]
+toList = KM.toList
+
+toAscList :: KeyMap v -> [(Key, v)]
+toAscList = M.toList . toMap
+
+elems :: KeyMap v -> [v]
+elems = KM.elems
+
+fromHashMap :: HashMap Key v -> KeyMap v
+fromHashMap = KM.fromHashMap
+
+toHashMap :: KeyMap v -> HashMap Key v
+toHashMap = KM.toHashMap
+
+fromHashMapText :: HashMap Text v -> KeyMap v
+fromHashMapText = KM.fromHashMapText
+
+toHashMapText :: KeyMap v -> HashMap Text v
+toHashMapText = KM.toHashMapText
+
+fromMap :: Map Key v -> KeyMap v
+fromMap = KM.fromList . M.toList
+
+toMap :: KeyMap v -> Map Key v
+toMap = M.fromList . KM.toList
+
+fromMapText :: Map Text v -> KeyMap v
+fromMapText = KM.fromMap . M.mapKeys K.fromText
+
+toMapText :: KeyMap v -> Map Text v
+toMapText = M.mapKeys K.toText . KM.toMap
+
+map :: (a -> b) -> KeyMap a -> KeyMap b
+map = KM.map
+
+mapWithKey :: (Key -> a -> b) -> KeyMap a -> KeyMap b
+mapWithKey f = KM.fromMap . M.mapWithKey f . KM.toMap
+
+traverseWithKey :: Applicative f => (Key -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
+traverseWithKey = KM.traverseWithKey
+
+foldr :: (a -> b -> b) -> b -> KeyMap a -> b
+foldr = KM.foldr
+
+foldr' :: (a -> b -> b) -> b -> KeyMap a -> b
+foldr' = KM.foldr'
+
+foldl :: (b -> a -> b) -> b -> KeyMap a -> b
+foldl = KM.foldl
+
+foldl' :: (b -> a -> b) -> b -> KeyMap a -> b
+foldl' = KM.foldl'
+
+foldMapWithKey :: Monoid m => (Key -> a -> m) -> KeyMap a -> m
+foldMapWithKey = KM.foldMapWithKey
+
+foldrWithKey :: (Key -> v -> a -> a) -> a -> KeyMap v -> a
+foldrWithKey = KM.foldrWithKey
+
+keys :: KeyMap v -> [Key]
+keys = KM.keys
+
+filter :: (v -> Bool) -> KeyMap v -> KeyMap v
+filter = KM.filter
+
+filterWithKey :: (Key -> v -> Bool) -> KeyMap v -> KeyMap v
+filterWithKey = KM.filterWithKey
+
+mapMaybe :: (a -> Maybe b) -> KeyMap a -> KeyMap b
+mapMaybe = KM.mapMaybe
+
+mapMaybeWithKey :: (Key -> v -> Maybe u) -> KeyMap v -> KeyMap u
+mapMaybeWithKey = KM.mapMaybeWithKey
+
+#endif
diff --git a/test/HaskellWorks/Data/AesonSpec.hs b/test/HaskellWorks/Data/AesonSpec.hs
--- a/test/HaskellWorks/Data/AesonSpec.hs
+++ b/test/HaskellWorks/Data/AesonSpec.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications #-}
 
 module HaskellWorks.Data.AesonSpec
   ( spec
@@ -8,6 +9,8 @@
 import HaskellWorks.Data.Aeson
 import Test.Hspec
 
+import qualified HaskellWorks.Data.Aeson.Compat.Map as JM
+
 {- HLINT ignore "Redundant do"        -}
 
 spec :: Spec
@@ -23,3 +26,14 @@
           , "two"    .= (2 :: Int)
           ]
     actual `shouldBe` expected
+  it "Re-exports complete" $ do
+    let _ = JM.toList
+    let _ = JM.toMap
+    let _ = JM.foldlWithKey
+    let _ = JM.fromHashMapText
+    let _ = JM.lookup @Int
+    let _ = JM.toHashMapText
+    let _ = JM.toList
+    let _ = JM.toMap
+
+    True
