diff --git a/haiji.cabal b/haiji.cabal
--- a/haiji.cabal
+++ b/haiji.cabal
@@ -2,7 +2,7 @@
 --  see http://haskell.org/cabal/users-guide/
 
 name:                haiji
-version:             0.3.3.0
+version:             0.3.4.0
 synopsis:            A typed template engine, subset of jinja2
 description:         Haiji is a template engine which is subset of jinja2.
                      This is designed to free from the unintended rendering result
@@ -65,6 +65,7 @@
                        Text.Haiji.Syntax.Expression
                        Text.Haiji.Syntax.Literal
                        Text.Haiji.Syntax.Literal.String
+                       Text.Haiji.Utils
   build-depends:       base >=4.7 && <5
                      , text
                      , attoparsec >=0.10
@@ -91,6 +92,9 @@
   hs-source-dirs:      test
   ghc-options:         -Wall -threaded
   default-language:    Haskell2010
+  -- Skip doctest for GHC 9. https://github.com/sol/doctest/issues/327
+  if impl(ghc >= 9.0) && impl(ghc < 9.3)
+    buildable: False
 
 test-suite tests
   type:                exitcode-stdio-1.0
diff --git a/src/Text/Haiji/Dictionary.hs b/src/Text/Haiji/Dictionary.hs
--- a/src/Text/Haiji/Dictionary.hs
+++ b/src/Text/Haiji/Dictionary.hs
@@ -18,7 +18,7 @@
        , retrieve
        ) where
 
-import Data.Aeson
+import Data.Aeson (ToJSON(..), Value(..), encode, object, (.=))
 import Data.Dynamic
 import qualified Data.HashMap.Strict as M
 import Data.Maybe
@@ -26,7 +26,6 @@
 #else
 import Data.Monoid
 #endif
-import qualified Data.Text as T
 import qualified Data.Text.Lazy as LT
 import qualified Data.Text.Lazy.Encoding as LT
 import Data.Type.Bool
@@ -38,6 +37,7 @@
 #define STAR *
 #endif
 import GHC.TypeLits
+import Text.Haiji.Utils (toKey)
 
 data Key (k :: Symbol) where
   Key :: KnownSymbol k => Key k
@@ -74,7 +74,7 @@
 instance (ToJSON (Dict d), ToJSON v, KnownSymbol k, Typeable v) => ToJSON (Dict ((k :-> v) ': d)) where
   toJSON dict = Object (a <> b) where
     (x, v, xs) = headKV dict
-    Object a = object [ T.pack (keyVal x) .= v ]
+    Object a = object [ toKey (keyVal x) .= v ]
     Object b = toJSON xs
     headKV :: (KnownSymbol k, Typeable v) => Dict ((k :-> v) ': d) -> (Key k, v, Dict d)
     headKV (Dict d) = (k, fromJust $ fromDynamic $ d M.! keyVal k, Dict $ M.delete (keyVal k) d) where
diff --git a/src/Text/Haiji/Runtime.hs b/src/Text/Haiji/Runtime.hs
--- a/src/Text/Haiji/Runtime.hs
+++ b/src/Text/Haiji/Runtime.hs
@@ -22,7 +22,6 @@
 import qualified Data.Aeson as JSON
 import qualified Data.Aeson.Types as JSON
 import Data.Maybe
-import qualified Data.HashMap.Strict as HM
 import Data.Scientific
 import qualified Data.Text as T
 import qualified Data.Text.Lazy as LT
@@ -30,6 +29,7 @@
 import Text.Haiji.Parse
 import Text.Haiji.Syntax
 import Text.Haiji.Types
+import Text.Haiji.Utils
 
 -- | Dynamically template loader (for template development use)
 readTemplateFile :: Environment -> FilePath -> IO (Template JSON.Value)
@@ -71,8 +71,8 @@
               [ runReader (haijiASTs env parentBlock children loopBody)
                           (let JSON.Object obj = p
                            in  JSON.Object
-                               $ HM.insert "loop" (loopVariables len ix)
-                               $ HM.insert (T.pack $ show k) x obj)
+                               $ insertValue "loop" (loopVariables len ix)
+                               $ insertValue (toKey $ show k) x obj)
               | (ix, x) <- zip [0..] (V.toList dicts)
               ]
          else maybe (return "") (haijiASTs env parentBlock children) elseBody
@@ -89,7 +89,7 @@
   do val <- eval rhs
      p <- ask
      return $ runReader (haijiASTs env parentBlock children scopes)
-       (let JSON.Object obj = p in  JSON.Object $ HM.insert (T.pack $ show lhs) val obj)
+       (let JSON.Object obj = p in  JSON.Object $ insertValue (toKey $ show lhs) val obj)
 
 loopVariables :: Integer -> Integer -> JSON.Value
 loopVariables len ix = JSON.object [ "first"     JSON..= (ix == 0)
@@ -108,7 +108,7 @@
   go (ExprIntegerLiteral n) = return $ JSON.Number $ scientific n 0
   go (ExprStringLiteral s) = return $ JSON.String $ T.pack $ unwrap s
   go (ExprBooleanLiteral b) = return $ JSON.Bool b
-  go (ExprVariable v) = either error id . JSON.parseEither (JSON.withObject (show v) (JSON..: (T.pack $ show v))) <$> ask
+  go (ExprVariable v) = either error id . JSON.parseEither (JSON.withObject (show v) (JSON..: (toKey $ show v))) <$> ask
   go (ExprParen e) = go e
   go (ExprRange [stop]) = do
     sstop <- either error id . JSON.parseEither (JSON.withScientific "range" return) <$> go stop
@@ -130,7 +130,7 @@
       _             -> error "range"
   go (ExprRange _) = error "unreachable"
   go (ExprAttributed e []) = go e
-  go (ExprAttributed e attrs) = either error id . JSON.parseEither (JSON.withObject (show $ last attrs) (JSON..: (T.pack $ show $ last attrs))) <$> go (ExprAttributed e $ init attrs)
+  go (ExprAttributed e attrs) = either error id . JSON.parseEither (JSON.withObject (show $ last attrs) (JSON..: (toKey $ show $ last attrs))) <$> go (ExprAttributed e $ init attrs)
   go (ExprFiltered e []) = go e
   go (ExprFiltered e filters) = applyFilter (last filters) $ ExprFiltered e $ init filters where
     applyFilter FilterAbs e' = either error id . JSON.parseEither (JSON.withScientific "abs" (return . JSON.Number . abs)) <$> go e'
diff --git a/src/Text/Haiji/Utils.hs b/src/Text/Haiji/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Haiji/Utils.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP #-}
+module Text.Haiji.Utils where
+
+import qualified Data.Aeson as JSON
+
+#if MIN_VERSION_aeson(2,0,0)
+import Data.String (fromString)
+import qualified Data.Aeson.KeyMap as JSON
+
+toKey :: String -> JSON.Key
+toKey = fromString
+
+insertValue :: JSON.Key -> JSON.Value -> JSON.KeyMap JSON.Value -> JSON.KeyMap JSON.Value
+insertValue = JSON.insert
+
+#else
+import qualified Data.Text as T
+import qualified Data.HashMap.Strict as HM
+
+toKey :: String -> T.Text
+toKey = T.pack
+
+insertValue :: T.Text -> JSON.Value -> HM.HashMap T.Text JSON.Value -> HM.HashMap T.Text JSON.Value
+insertValue = HM.insert
+#endif
+
+
+
