diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,18 @@
 # Revision history for greskell-core
 
+## 1.0.0.0  -- 2021-12-28
+
+* **BREAKING CHANGE**:  `GObject` variant of `GValueBody` is now based on `KeyMap` from `aeson-2.0`.
+  Before, it was based on `HashMap Text`.
+  As a result, signature of the following functions has been changed.
+  * `parseToGMap`
+  * `parseToGMapEntry`
+  * `(.:)`
+* **BREAKING CHANGE**: Remove `FromGraphSON` instance for `Data.Semigroup.Option`, which is deprecated.
+* Add `FromGraphSON` instance to `KeyMap` and `Key` from `aeson-2.0`.
+* Confirm test with `aeson-2.0.2.0`, `semigroups-0.20` and `hashable-1.4.0.1`, `doctest-0.19.0`, `doctest-0.20.0`.
+
+
 ## 0.1.3.7  -- 2021-11-08
 
 * Confirm test with `base-4.15.0.0`
diff --git a/greskell-core.cabal b/greskell-core.cabal
--- a/greskell-core.cabal
+++ b/greskell-core.cabal
@@ -1,5 +1,5 @@
 name:                   greskell-core
-version:                0.1.3.7
+version:                1.0.0.0
 author:                 Toshio Ito <debug.ito@gmail.com>
 maintainer:             Toshio Ito <debug.ito@gmail.com>
 license:                BSD3
@@ -31,12 +31,12 @@
   other-modules:        Data.Greskell.GraphSON.GraphSONTyped,
                         Data.Greskell.GraphSON.Core
   build-depends:        base >=4.9.0.0 && <4.16,
-                        aeson >=1.0.2.1 && <1.6,
+                        aeson >=2.0.2.0 && <2.1,
                         unordered-containers >=0.2.7.1 && <0.3,
-                        hashable >=1.2.6.1 && <1.4,
+                        hashable >=1.2.6.1 && <1.5,
                         scientific >=0.3.4.9 && <0.4,
                         text >=1.2.2.1 && <1.3,
-                        semigroups >=0.18.2 && <0.20,
+                        semigroups >=0.18.2 && <0.21,
                         vector >=0.12.0.1 && <0.13,
                         containers >=0.5.7.1 && <0.7,
                         uuid >=1.3.13 && <1.4
@@ -68,7 +68,7 @@
   main-is:              DocTest.hs
   build-tool-depends:   doctest-discover:doctest-discover
   build-depends:        base,
-                        doctest >=0.11 && <0.19,
+                        doctest >=0.11 && <0.21,
                         doctest-discover >=0.1.0.7 && <0.3
 
 
diff --git a/src/Data/Greskell/GMap.hs b/src/Data/Greskell/GMap.hs
--- a/src/Data/Greskell/GMap.hs
+++ b/src/Data/Greskell/GMap.hs
@@ -31,10 +31,11 @@
     FromJSONKey, fromJSONKey, FromJSONKeyFunction(..), ToJSONKey
   )
 import Data.Aeson.Types (Parser)
+import Data.Aeson.KeyMap (KeyMap)
+import qualified Data.Aeson.KeyMap as KM
+import qualified Data.Aeson.Key as Key
 import Data.Foldable (length, Foldable)
 import Data.Hashable (Hashable)
-import Data.HashMap.Strict (HashMap)
-import qualified Data.HashMap.Strict as HM
 import qualified Data.Map as M
 import Data.Text (Text, intercalate, unpack)
 import Data.Traversable (Traversable, traverse)
@@ -153,8 +154,8 @@
 parseToGMap :: (IsList (c k v), Item (c k v) ~ (k,v))
             => (s -> Parser k) -- ^ key parser
             -> (s -> Parser v) -- ^ value parser
-            -> (HashMap Text s -> Parser (c k v)) -- ^ object parser
-            -> Either (HashMap Text s) (Vector s) -- ^ input object or flattened key-values.
+            -> (KeyMap s -> Parser (c k v)) -- ^ object parser
+            -> Either (KeyMap s) (Vector s) -- ^ input object or flattened key-values.
             -> Parser (GMap c k v)
 parseToGMap _ _ op (Left o) = fmap (GMap False) $ op o
 parseToGMap kp vp _ (Right v) = fmap (GMap True . unFlattenedMap) $ parseToFlattenedMap kp vp v
@@ -213,14 +214,14 @@
 
 parseKeyValueToEntry :: (s -> Parser k)
                      -> (s -> Parser v)
-                     -> HashMap Text s
+                     -> KeyMap s
                      -> Parser (Maybe (GMapEntry k v))
 parseKeyValueToEntry kp vp o =
   if length o /= 2
   then return Nothing
   else do
-    mk <- parseIfPresent kp $ HM.lookup "key" o
-    mv <- parseIfPresent vp $ HM.lookup "value" o
+    mk <- parseIfPresent kp $ KM.lookup "key" o
+    mv <- parseIfPresent vp $ KM.lookup "value" o
     return $ GMapEntry False <$> mk <*> mv
   where
     parseIfPresent :: (a -> Parser v) -> Maybe a -> Parser (Maybe v)
@@ -228,12 +229,12 @@
 
 parseSingleEntryObjectToEntry :: FromJSONKey k
                               => (s -> Parser v)
-                              -> HashMap Text s
+                              -> KeyMap s
                               -> Parser (Maybe (GMapEntry k v))
 parseSingleEntryObjectToEntry vp o =
-  case HM.toList o of
+  case KM.toList o of
    [(raw_key, raw_val)] -> do
-     key <- parseKey raw_key
+     key <- parseKey $ Key.toText raw_key
      val <- vp raw_val
      return $ Just $ GMapEntry False key val
    _ -> return Nothing
@@ -248,11 +249,7 @@
                                    ++ " It expects that the entry key is parsed from the text key in JSON Object,"
                                    ++ " but the key type does not support it."
                                  )
-#if MIN_VERSION_aeson(1,5,0)
       FromJSONKeyCoerce -> return $ fmap return coerce
-#else
-      FromJSONKeyCoerce _ -> return $ fmap return unsafeCoerce
-#endif
 
 orElseM :: Monad m => m (Maybe a) -> m (Maybe a) -> m (Maybe a)
 orElseM act_a act_b = do
@@ -265,7 +262,7 @@
 parseToGMapEntry :: FromJSONKey k
                  => (s -> Parser k) -- ^ key parser
                  -> (s -> Parser v) -- ^ value parser
-                 -> Either (HashMap Text s) (Vector s) -- ^ input object or flattened key-values
+                 -> Either (KeyMap s) (Vector s) -- ^ input object or flattened key-values
                  -> Parser (GMapEntry k v)
 parseToGMapEntry kp vp (Right vec) = do
   avec <- parseToAVec kp vp vec
@@ -276,7 +273,7 @@
   m_ret <- parseKeyValueToEntry kp vp o `orElseM` parseSingleEntryObjectToEntry vp o
   case m_ret of
    Just ret -> return ret
-   Nothing -> fail ("Unexpected structure of Object: got keys: " ++ (unpack $ intercalate ", " $ HM.keys o))
+   Nothing -> fail ("Unexpected structure of Object: got keys: " ++ (unpack $ intercalate ", " $ map Key.toText $ KM.keys o))
 
 -- | Map to \"g:Map\".
 instance GraphSONTyped (GMapEntry k v) where
diff --git a/src/Data/Greskell/GraphSON.hs b/src/Data/Greskell/GraphSON.hs
--- a/src/Data/Greskell/GraphSON.hs
+++ b/src/Data/Greskell/GraphSON.hs
@@ -41,10 +41,13 @@
 import qualified Data.Aeson as Aeson
 import Data.Aeson.Types (Parser)
 import qualified Data.Aeson.Types as Aeson (parseEither)
+import Data.Aeson.KeyMap (KeyMap)
+import qualified Data.Aeson.KeyMap as KM
+import Data.Aeson.Key (Key)
+import qualified Data.Aeson.Key as Key
 import Data.Foldable (Foldable(foldr))
 import Data.Functor.Identity (Identity(..))
 import Data.HashMap.Strict (HashMap)
-import qualified Data.HashMap.Strict as HM
 import qualified Data.HashMap.Lazy as L (HashMap)
 import Data.HashSet (HashSet)
 import Data.Hashable (Hashable(..))
@@ -153,11 +156,11 @@
 
 -- | Like Aeson's 'Aeson..:', but for 'FromGraphSON'.
 --
--- @since 0.1.2.0
-(.:) :: FromGraphSON a => HashMap Text GValue -> Text -> Parser a
-go .: label = maybe failure parseGraphSON $ HM.lookup label go
+-- @since 1.0.0.0
+(.:) :: FromGraphSON a => KeyMap GValue -> Key -> Parser a
+go .: label = maybe failure parseGraphSON $ KM.lookup label go
   where
-    failure = fail ("Cannot find field " ++ unpack label)
+    failure = fail ("Cannot find field " ++ Key.toString label)
 
 -- | Implementation of 'parseJSON' based on 'parseGraphSON'. The input
 -- 'Value' is first converted to 'GValue', and it's parsed to the
@@ -212,6 +215,12 @@
 instance FromGraphSON IntSet where
   parseGraphSON = parseUnwrapAll
 
+-- | First convert to 'Text', and convert to 'Key'.
+--
+-- @since 1.0.0.0
+instance FromGraphSON Key where
+  parseGraphSON = fmap Key.fromText . parseGraphSON
+
 ---- List instances
 
 instance FromGraphSON a => FromGraphSON [a] where
@@ -283,7 +292,7 @@
     b -> fail ("Expects GArray, but got " ++ show b)
 
 parseGObjectToTraversal :: (Traversable t, FromJSON (t GValue), FromGraphSON v)
-                        => HashMap Text GValue
+                        => KeyMap GValue
                         -> Parser (t v)
 parseGObjectToTraversal o = traverse parseGraphSON =<< (parseJSON $ Object $ fmap toJSON o)
 
@@ -322,6 +331,12 @@
       mapToIntMap :: L.Map Int v -> L.IntMap v
       mapToIntMap = LMap.foldrWithKey LIntMap.insert mempty
 
+-- | First convert to 'L.Map' with 'Text' key, and convert to 'KeyMap'.
+--
+-- @since 1.0.0.0
+instance FromGraphSON v => FromGraphSON (KeyMap v) where
+  parseGraphSON = fmap KM.fromMap . parseGraphSON
+
 ---- Maybe and Either
 
 -- | Parse 'GNull' into 'Nothing'.
@@ -335,9 +350,6 @@
 
 ---- Trivial wrapper for Maybe
 
--- | @since 0.1.3.0
-instance FromGraphSON a => FromGraphSON (S.Option a) where
-  parseGraphSON = fmap S.Option . parseGraphSON
 -- | @since 0.1.3.0
 instance FromGraphSON a => FromGraphSON (M.First a) where
   parseGraphSON = fmap M.First . parseGraphSON
diff --git a/src/Data/Greskell/GraphSON/GValue.hs b/src/Data/Greskell/GraphSON/GValue.hs
--- a/src/Data/Greskell/GraphSON/GValue.hs
+++ b/src/Data/Greskell/GraphSON/GValue.hs
@@ -28,6 +28,7 @@
 import Data.Aeson
   ( ToJSON(toJSON), FromJSON(parseJSON), Value(..)
   )
+import Data.Aeson.KeyMap (KeyMap)
 import Data.Aeson.Types (Parser)
 import Data.Foldable (foldl')
 import Data.Hashable (Hashable(..))
@@ -56,9 +57,9 @@
 
 -- | 'GValue' without the top-level 'GraphSON' wrapper.
 --
--- @since 0.1.2.0
+-- @since 1.0.0.0
 data GValueBody =
-    GObject !(HashMap Text GValue)
+    GObject !(KeyMap GValue)
   | GArray !(Vector GValue)
   | GString !Text
   | GNumber !Scientific
diff --git a/src/Data/Greskell/Greskell.hs b/src/Data/Greskell/Greskell.hs
--- a/src/Data/Greskell/Greskell.hs
+++ b/src/Data/Greskell/Greskell.hs
@@ -35,9 +35,10 @@
 
 import Data.Aeson (Value)
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.KeyMap as KM
+import qualified Data.Aeson.Key as Key
 import Data.Bifunctor (bimap)
 import Data.Foldable (toList)
-import qualified Data.HashMap.Lazy as HM
 import Data.Monoid (Monoid(..))
 import Data.Ratio (numerator, denominator, Rational)
 import Data.Scientific (Scientific, coefficient, base10Exponent)
@@ -222,11 +223,11 @@
 value (Aeson.String s) = unsafeToValue $ string s
 value (Aeson.Array v) = unsafeToValue $ list $ map value $ toList v
 value (Aeson.Object obj)
-  | HM.null obj = unsafeGreskellLazy "[:]"
-  | otherwise = unsafeGreskellLazy $ toGroovyMap $ HM.toList obj
+  | KM.null obj = unsafeGreskellLazy "[:]"
+  | otherwise = unsafeGreskellLazy $ toGroovyMap $ KM.toList obj
   where
     toGroovyMap pairs = "[" <> TL.intercalate "," (map toPairText pairs) <> "]"
-    toPairText (key, val) = (toGremlinLazy $ string key) <> ":" <> (toGremlinLazy $ value val)
+    toPairText (key, val) = (toGremlinLazy $ string $ Key.toText key) <> ":" <> (toGremlinLazy $ value val)
 
 -- | Integer literal as 'Value' type.
 --
diff --git a/test/Data/Greskell/GMapSpec.hs b/test/Data/Greskell/GMapSpec.hs
--- a/test/Data/Greskell/GMapSpec.hs
+++ b/test/Data/Greskell/GMapSpec.hs
@@ -2,6 +2,7 @@
 module Data.Greskell.GMapSpec (main,spec) where
 
 import Data.Aeson (eitherDecode, object, (.=), toJSON, Value(..))
+import qualified Data.Aeson.KeyMap as KM
 import Data.HashMap.Strict (HashMap)
 import qualified Data.HashMap.Strict as HM
 import Data.List (isInfixOf)
@@ -51,8 +52,8 @@
                                     String "a",   Number 1
                                   ]
           (Object got) = toJSON val
-      HM.lookup "@type" got `shouldBe` (Just $ String "g:Map")
-      let (Just (Array got_flat)) = HM.lookup "@value" got
+      KM.lookup "@type" got `shouldBe` (Just $ String "g:Map")
+      let (Just (Array got_flat)) = KM.lookup "@value" got
       pairList got_flat `shouldMatchList` pairList exp_flat
     specify "FromJSON empty" $ do
       let val_empty :: GraphSON (GMap HashMap String Int)
diff --git a/test/Data/Greskell/GraphSONSpec.hs b/test/Data/Greskell/GraphSONSpec.hs
--- a/test/Data/Greskell/GraphSONSpec.hs
+++ b/test/Data/Greskell/GraphSONSpec.hs
@@ -3,6 +3,7 @@
 
 import Data.Aeson (object, (.=), ToJSON(..), FromJSON(..), Value(..))
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.KeyMap as KM
 import Data.Aeson.Types (parseEither, Value(..), Parser)
 import qualified Data.ByteString.Lazy as BSL
 import Data.Either (isLeft)
@@ -189,9 +190,9 @@
     fromToJSON "wrapped array" (gson "g:List" "[null, \"foo\", 100]")
       (wrapped "g:List" $ GArray $ fmap bare $ V.fromList [GNull, GString "foo", GNumber 100])
     fromToJSON "bare object" "{\"foo\": \"bar\", \"hoge\": 99, \"quux\": null}"
-      (bare $ GObject $ fmap bare $ HM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])
+      (bare $ GObject $ fmap bare $ KM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])
     fromToJSON "wrapped object" (gson "g:Map" "{\"foo\": \"bar\", \"hoge\": 99, \"quux\": null}")
-      (wrapped "g:Map" $ GObject $ fmap bare $ HM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])
+      (wrapped "g:Map" $ GObject $ fmap bare $ KM.fromList [("foo", GString "bar"), ("hoge", GNumber 99), ("quux", GNull)])
     nested_spec
     double_wrap_spec
     decode_error_spec
@@ -208,7 +209,7 @@
 nested_spec = fromToJSON "mixed nested" nestedSample expected
   where
     expected = wrapped "g:List" $ GArray $ V.fromList [ bare $ GNumber 100, exp_a, exp_b ]
-    exp_a = wrapped "g:Map" $ GObject $ HM.fromList
+    exp_a = wrapped "g:Map" $ GObject $ KM.fromList
             [ ("foo", bare $ GNumber 100),
               ("bar", wrapped "g:Int" $ GNumber 200)
             ]
@@ -218,7 +219,7 @@
               exp_c,
               wrapped "g:Boolean" $ GBool False
             ]
-    exp_c = bare $ GObject $ HM.fromList
+    exp_c = bare $ GObject $ KM.fromList
             [ ("xxx", wrapped "g:Int" $ GNumber 200),
               ("yyy", bare $ GBool True)
             ]
@@ -230,7 +231,7 @@
 double_wrap_spec = fromToJSON "double wrapped" input expected
   where
     input = gson "g:Object" $ gson "g:Int" "100"
-    expected = wrapped "g:Object" $ GObject $ HM.fromList
+    expected = wrapped "g:Object" $ GObject $ KM.fromList
                [ ("@type", bare $ GString "g:Int"),
                  ("@value", bare $ GNumber 100)
                ]
