diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for yaml-combinators
 
+## 1.1.2.1
+
+* Require `aeson ^>= 2.0`
+
 ## 1.1.2
 
 * Add an `extraFields` combinator
diff --git a/src/Data/Yaml/Combinators.hs b/src/Data/Yaml/Combinators.hs
--- a/src/Data/Yaml/Combinators.hs
+++ b/src/Data/Yaml/Combinators.hs
@@ -38,9 +38,11 @@
   , validate
   ) where
 
-import Data.Aeson (Value(..), Object, Array)
 import Data.Scientific
 import Data.Yaml (decodeEither', encode)
+import Data.Aeson (Array, Object, Value (..))
+import qualified Data.Aeson.Key as Key
+import qualified Data.Aeson.KeyMap as KeyMap
 import Data.Text (Text)
 import Data.List
 import Data.Maybe
@@ -52,7 +54,6 @@
 import Control.Monad.Trans.State as State
 import Data.Vector (Vector)
 import qualified Data.Vector as V
-import qualified Data.HashMap.Strict as HM
 import Data.HashSet (HashSet)
 import qualified Data.HashSet as HS
 import Data.Ord
@@ -61,10 +62,6 @@
 import Generics.SOP.TH
 import Data.Yaml.Combinators.Free as Free
 
--- $setup
--- >>> :set -XOverloadedStrings -XTypeApplications
--- >>> import Data.Semigroup
-
 -- orphan Value instances
 deriveGeneric ''Value
 
@@ -419,7 +416,7 @@
 
 data FieldParserBase a where
   OneField
-    :: Text -- ^ field name
+    :: Text -- field name
     -> ReaderT Object Validation a
     -> FieldParserBase a
   ExtraFields :: FieldParserBase Object
@@ -432,7 +429,7 @@
   -> FieldParser a
 field name p = FieldParser . Free.lift . OneField name $
   ReaderT $ \o ->
-    case HM.lookup name o of
+    case KeyMap.lookup (Key.fromText name) o of
       Nothing -> Validation . Left $ ParseError 0 $ ExpectedAsPartOf (HS.singleton $ "field " ++ show name) $ Object o
       Just v -> runParserV p v
 
@@ -444,7 +441,7 @@
   -> Parser a -- ^ value parser
   -> FieldParser (Maybe a)
 optField name p = FieldParser . Free.lift . OneField name $
-  ReaderT $ \o -> traverse (runParserV p) $ HM.lookup name o
+  ReaderT $ \o -> traverse (runParserV p) $ KeyMap.lookup (Key.fromText name) o
 
 -- | Declare an optional object field with the given name and with a default
 -- to use if the field is absent.
@@ -531,12 +528,12 @@
       -- some metainformation: which fields are requested by the parser,
       -- and whether extra fields are requested too (and therefore allowed)
       StrictPair requested_names (Any requested_extra_fields) = Free.foldMap (\case
-        OneField name _ -> StrictPair (HM.singleton name ()) (Any False)
+        OneField name _ -> StrictPair (KeyMap.singleton (Key.fromText name) ()) (Any False)
         ExtraFields -> StrictPair mempty (Any True)
         ) fp
-      extra_fields = HM.difference o requested_names
+      extra_fields = KeyMap.difference o requested_names
       extra_fields_error =
-        when (not requested_extra_fields && not (HM.null extra_fields)) $
+        when (not requested_extra_fields && not (KeyMap.null extra_fields)) $
           Validation . Left $ ParseError 0 $
             UnexpectedAsPartOf (Object extra_fields) (Object o)
     in
diff --git a/tests/doctests.hs b/tests/doctests.hs
deleted file mode 100644
--- a/tests/doctests.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Test.DocTest
-main = doctest ["-isrc", "src/Data/Yaml/Combinators.hs"]
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -1,12 +1,12 @@
-{-# LANGUAGE OverloadedLists, OverloadedStrings #-}
+{-# LANGUAGE OverloadedLists, OverloadedStrings, TypeApplications #-}
 import Data.Yaml.Combinators
 import Data.Functor
 import Test.Tasty
 import Test.Tasty.HUnit
 import Data.Aeson hiding (object)
+import qualified Data.Aeson.KeyMap as KeyMap
 import qualified Data.Text as T
 import Data.Monoid
-import qualified Data.HashMap.Strict as HM
 
 main = defaultMain tests
 
@@ -27,7 +27,7 @@
       runParser (array string) (Array [String "hi"]) @?=
         Right ["hi"]
   , testCase "Expect an array, get an object" $
-      runParser (array string) (Object HM.empty) @?=
+      runParser (array string) (Object mempty) @?=
         Left (ParseError 0 $ ExpectedInsteadOf ["Array"] (Object []))
   , testCase "Expect an array of Strings, get an array of Numbers" $
       runParser (array string) (Array [Number 3]) @?=
@@ -151,4 +151,34 @@
       runParser (even_str <> even_str) (String "x")
       @?=
       Left (ParseError 1 (ExpectedInsteadOf ["even-length string"] (String "x")))
+  -- These used to be proper doctests, but now they are just haddocks, because doctest is janky
+  , testCase "doctests" $ do
+      parse string "howdy" @?= Right "howdy"
+      parse (theString "hello") "hello" @?= Right ()
+      parse (theString "hello") "bye" @?= Left "Expected \"hello\" instead of:\n\nbye\n"
+      parse (array string) "[a,b,c]" @?= Right ["a","b","c"]
+      parse (theArray $ (,) <$> element string <*> element bool) "[f, true]" @?= Right ("f",True)
+      parse number "3.14159" @?= Right 3.14159
+      parse (integer @Int) "2017" @?= Right 2017
+      parse bool "yes" @?= Right True
+      parse null_ "null" @?= Right ()
+      let acceptEven n = if even n then Right n else Left "an even number"
+      parse (integer @Int `validate` acceptEven) "2017"
+        @?= Left "Expected an even number instead of:\n\n2017\n"
+      let p = object (Right <$ theField "type" "number" <*> field "value" number)
+                <> object (Left  <$ theField "type" "string" <*> field "value" string)
+      parse p "{type: string, value: abc}" @?= Right (Left "abc")
+      parse p "{type: number, value: 123}" @?= Right (Right 123.0)
+      let fp = field "name" string
+      parse (object fp) "name: Anton" @?= Right "Anton"
+      parse (object fp) "{name: Anton, age: 2}"
+        @?= Left "Unexpected \n\nage: 2\n\nas part of\n\nage: 2\nname: Anton\n"
+      parse (object $ (,) <$> fp <*> extraFields) "{name: Anton, age: 2}"
+        @?= Right ("Anton", KeyMap.fromList [("age", Number 2.0)])
+      parse (object $ fp <* extraFields) "{name: Anton, age: 2}" @?= Right "Anton"
+      let p = object $ (,) <$> field "name" string <*> optField "age" (integer @Int)
+      parse p "{ name: Anton, age: 2 }" @?= Right ("Anton", Just 2)
+      parse p "name: Roma" @?= Right ("Roma", Nothing)
+      parse anyValue "[one, two, {three: four}]"
+        @?= Right (Array [String "one", String "two", Object (KeyMap.fromList [("three", String "four")])])
   ]
diff --git a/yaml-combinators.cabal b/yaml-combinators.cabal
--- a/yaml-combinators.cabal
+++ b/yaml-combinators.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                yaml-combinators
-version:             1.1.2
+version:             1.1.2.1
 synopsis:            YAML parsing combinators for improved validation and error reporting
 description:         Based on the article
                      <https://ro-che.info/articles/2015-07-26-better-yaml-parsing Better Yaml Parsing>.
@@ -10,13 +10,13 @@
 license:             MIT
 license-file:        LICENSE
 author:              Roman Cheplyaka
-maintainer:          roma@ro-che.info
+maintainer:          roma@ro-che.info, mitchellwrosen@gmail.com
 copyright:           (c) 2015 Signal Vine, LLC
                      (c) 2017 Roman Cheplyaka
 category:            Text
 build-type:          Simple
 extra-source-files:  ChangeLog.md, README.md
-cabal-version:       >=1.10
+cabal-version:       2.0
 
 source-repository head
   type:     git
@@ -31,7 +31,7 @@
     Data.Yaml.Combinators.Free
   -- other-extensions:
   build-depends:
-    aeson,
+    aeson ^>= 2.0,
     base >= 4.11 && < 5,
     bytestring,
     generics-sop >= 0.5,
@@ -61,14 +61,3 @@
     , text
     , unordered-containers
     , yaml-combinators
-
-test-suite doctests
-  type:          exitcode-stdio-1.0
-  ghc-options:   -threaded
-  hs-source-dirs:
-    tests
-  main-is:
-    doctests.hs
-  build-depends: base, doctest
-  default-language:
-    Haskell2010
