diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,6 +1,7 @@
+cabal-version:      2.2
 name:               aeson
-version:            2.2.1.0
-license:            BSD3
+version:            2.2.2.0
+license:            BSD-3-Clause
 license-file:       LICENSE
 category:           Text, Web, JSON
 copyright:
@@ -11,19 +12,17 @@
 maintainer:         Adam Bergmark <adam@bergmark.nl>
 stability:          experimental
 tested-with:
-  GHC ==8.2.2
-   || ==8.4.4
-   || ==8.6.5
+  GHC ==8.6.5
    || ==8.8.4
    || ==8.10.7
    || ==9.0.2
    || ==9.2.8
-   || ==9.4.7
-   || ==9.6.3
-   || ==9.8.1
+   || ==9.4.8
+   || ==9.6.5
+   || ==9.8.2
+   || ==9.10.1
 
 synopsis:           Fast JSON parsing and encoding
-cabal-version:      1.12
 homepage:           https://github.com/haskell/aeson
 bug-reports:        https://github.com/haskell/aeson/issues
 build-type:         Simple
@@ -84,8 +83,6 @@
     Data.Aeson.Internal.TH
     Data.Aeson.Internal.Unescape
     Data.Aeson.Internal.UnescapeFromText
-    Data.Aeson.Internal.Word8
-    Data.Aeson.Internal.Word16
     Data.Aeson.Parser.Time
     Data.Aeson.Types.Class
     Data.Aeson.Types.FromJSON
@@ -95,51 +92,49 @@
 
   -- GHC bundled libs
   build-depends:
-      base              >=4.10.0.0 && <5
+    , base              >=4.12.0.0 && <5
     , bytestring        >=0.10.8.2 && <0.13
-    , containers        >=0.5.10.2 && <0.7
-    , deepseq           >=1.4.3.0  && <1.6
+    , containers        >=0.6.0.1  && <0.8
+    , deepseq           >=1.4.4.0  && <1.6
     , exceptions        >=0.10.4   && <0.11
     , ghc-prim          >=0.5.0.0  && <0.12
-    , template-haskell  >=2.12.0.0 && <2.22
+    , template-haskell  >=2.14.0.0 && <2.23
     , text              >=1.2.3.0  && <1.3  || >=2.0 && <2.2
     , time              >=1.8.0.2  && <1.13
 
   -- Compat
   build-depends:
-      generically  >=0.1   && <0.2
+    , generically  >=0.1   && <0.2
     , time-compat  >=1.9.6 && <1.10
 
-  if !impl(ghc >=8.6)
-    build-depends: contravariant >=1.4.1 && <1.6
-
   if !impl(ghc >=9.0)
     build-depends: integer-gmp
 
   -- Other dependencies
   build-depends:
-      data-fix              >=0.3.2    && <0.4
-    , dlist                 >=1.0      && <1.1
-    , hashable              >=1.4.2.0  && <1.5
-    , indexed-traversable   >=0.1.2    && <0.2
-    , integer-conversion    >=0.1      && <0.2
-    , integer-logarithms    >=1.0.3.1  && <1.1
-    , network-uri           >=2.6.4.1  && <2.7
-    , OneTuple              >=0.4.1.1  && <0.5
-    , primitive             >=0.8.0.0  && <0.9
-    , QuickCheck            >=2.14.3   && <2.15
-    , scientific            >=0.3.7.0  && <0.4
-    , semialign             >=1.3      && <1.4
-    , strict                >=0.5      && <0.6
-    , tagged                >=0.8.7    && <0.9
-    , text-iso8601          >=0.1      && <0.2
-    , text-short            >=0.1.5    && <0.2
-    , th-abstraction        >=0.5.0.0  && <0.7
-    , these                 >=1.2      && <1.3
-    , unordered-containers  >=0.2.10.0 && <0.3
-    , uuid-types            >=1.0.5    && <1.1
-    , vector                >=0.13.0.0 && <0.14
-    , witherable            >=0.4.2    && <0.5
+    , character-ps          ^>=0.1
+    , data-fix              ^>=0.3.2
+    , dlist                 ^>=1.0
+    , hashable              ^>=1.4.2.0
+    , indexed-traversable   ^>=0.1.2
+    , integer-conversion    ^>=0.1
+    , integer-logarithms    ^>=1.0.3.1
+    , network-uri           ^>=2.6.4.1
+    , OneTuple              ^>=0.4.1.1
+    , primitive             ^>=0.8.0.0  || ^>=0.9.0.0
+    , QuickCheck            ^>=2.14.3 || ^>=2.15
+    , scientific            ^>=0.3.7.0
+    , semialign             ^>=1.3
+    , strict                ^>=0.5
+    , tagged                ^>=0.8.7
+    , text-iso8601          ^>=0.1
+    , text-short            ^>=0.1.5
+    , th-abstraction        ^>=0.5.0.0  || ^>=0.6.0.0 || ^>=0.7.0.0
+    , these                 ^>=1.2
+    , unordered-containers  ^>=0.2.10.0
+    , uuid-types            ^>=1.0.5
+    , vector                ^>=0.13.0.0
+    , witherable            ^>=0.4.2
 
   ghc-options:      -Wall
 
@@ -198,7 +193,7 @@
     UnitTests.UTCTime
 
   build-depends:
-      aeson
+    , aeson
     , base
     , base-compat
     , base-orphans          >=0.5.3  && <0.10
@@ -207,7 +202,7 @@
     , containers
     , data-fix
     , deepseq
-    , Diff                  >=0.4    && <0.5
+    , Diff                  >=0.4    && <0.6
     , directory
     , dlist
     , filepath
@@ -220,7 +215,7 @@
     , network-uri
     , OneTuple
     , primitive
-    , QuickCheck            >=2.14.2 && <2.15
+    , QuickCheck            >=2.14.2 && <2.16
     , quickcheck-instances  >=0.3.29 && <0.4
     , scientific
     , strict
@@ -243,7 +238,7 @@
     build-depends: integer-gmp
 
   if impl(ghc >=9.2 && <9.7)
-    build-depends: nothunks >=0.1.4 && <0.2
+    build-depends: nothunks >=0.1.4 && <0.3
 
 source-repository head
   type:     git
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
 For the latest version of this document, please see [https://github.com/haskell/aeson/blob/master/changelog.md](https://github.com/haskell/aeson/blob/master/changelog.md).
 
+### 2.2.2.0
+
+* Support GHC-8.6.5...9.10.1
+* Depend on `character-ps` instead of defining own Word8 pattern synonyms
+
 ### 2.2.1.0
 
 * Add `Data.Aeson.RFC8785`, a JSON Canonicalization Scheme implementation
diff --git a/src/Data/Aeson/Decoding/ByteString.hs b/src/Data/Aeson/Decoding/ByteString.hs
--- a/src/Data/Aeson/Decoding/ByteString.hs
+++ b/src/Data/Aeson/Decoding/ByteString.hs
@@ -18,12 +18,12 @@
 import qualified Data.ByteString              as BS
 import qualified Data.ByteString.Unsafe       as BS.Unsafe
 import qualified Data.Scientific              as Sci
+import qualified Data.Word8.Patterns          as W8
 
 import           Data.Aeson.Decoding.Internal
 import           Data.Aeson.Decoding.Tokens
 import           Data.Aeson.Internal.Text     (unsafeDecodeASCII)
 import           Data.Aeson.Internal.Unescape (unescapeText)
-import           Data.Aeson.Internal.Word8
 
 -- | Lex (and parse) strict 'ByteString' into 'Tokens' stream.
 --
@@ -42,17 +42,17 @@
         -> ByteString         -- whole input, needed for number parsing
         -> (ByteString -> k)  -- continuation
         -> Tokens k String
-    tokenCase W8_OPEN_CURLY   !bs !_   k      = TkRecordOpen (goR bs k)
-    tokenCase W8_OPEN_SQUARE   bs  _   k      = TkArrayOpen (goA bs k)
-    tokenCase W8_DOUBLE_QUOTE  bs  _   k      = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
-    tokenCase W8_MINUS         bs  _   k      = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
+    tokenCase W8.LEFT_CURLY   !bs !_   k      = TkRecordOpen (goR bs k)
+    tokenCase W8.LEFT_SQUARE   bs  _   k      = TkArrayOpen (goA bs k)
+    tokenCase W8.DOUBLE_QUOTE  bs  _   k      = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
+    tokenCase W8.HYPHEN        bs  _   k      = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
     tokenCase w                _   wbs k
-        | W8_0 <= w, w <= W8_9                = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
-    tokenCase W8_n             bs  _   k
+        | W8.DIGIT_0 <= w, w <= W8.DIGIT_9    = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
+    tokenCase W8.LOWER_N       bs  _   k
         | Just bs1 <- stripPrefix "ull" 3 bs  = TkLit LitNull (k bs1)
-    tokenCase W8_t             bs  _   k
+    tokenCase W8.LOWER_T       bs  _   k
         | Just bs1 <- stripPrefix "rue" 3 bs  = TkLit LitTrue (k bs1)
-    tokenCase W8_f             bs  _   k
+    tokenCase W8.LOWER_F       bs  _   k
         | Just bs1 <- stripPrefix "alse" 4 bs = TkLit LitFalse (k bs1)
     tokenCase _                _   wbs _      = tkErr $ "Unexpected " ++ showBeginning wbs ++ ", expecting JSON value"
 
@@ -60,33 +60,33 @@
     goA :: Parser TkArray k
     goA (skipSpace -> bs) k = case BS.uncons bs of
         Nothing         -> tkErrEOF "JSON value or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W8.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
         Just (w,  !bs1) -> TkItem $ tokenCase w bs1 bs $ \bs2 -> goA1 bs2 k
 
     goA1 :: Parser TkArray k
     goA1 (skipSpace -> bs) k = case BS.uncons bs of
         Nothing                      -> tkErrEOF ", or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
-        Just (W8_COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
+        Just (W8.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W8.COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
         _                            -> tkErrBS bs ", or ]"
 
     -- Record
     goR :: Parser TkRecord k
     goR (skipSpace -> bs) k = case BS.uncons bs of
         Nothing                       -> tkErrEOF "record key literal or }"
-        Just (W8_DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
-        Just (W8_CLOSE_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
+        Just (W8.DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
+        Just (W8.RIGHT_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
         Just _                        -> tkErrBS bs "record key literal or }"
 
     -- after record pair, expecting ," or }
     goR1 :: Parser TkRecord k
     goR1 (skipSpace -> bs) k = case BS.uncons bs of
         Nothing                           -> tkErr "Unexpected end-of-input, expecting , or }"
-        Just (W8_COMMA, !bs1) -> case BS.uncons (skipSpace bs1) of
+        Just (W8.COMMA, !bs1) -> case BS.uncons (skipSpace bs1) of
             Nothing                      -> tkErrEOF "key literal"
-            Just (W8_DOUBLE_QUOTE, !bs2) -> goRK bs2 k
+            Just (W8.DOUBLE_QUOTE, !bs2) -> goRK bs2 k
             Just _                       -> tkErrBS bs "key literal"
-        Just (W8_CLOSE_CURLY, !bs1)       -> TkRecordEnd (k bs1)
+        Just (W8.RIGHT_CURLY, !bs1)       -> TkRecordEnd (k bs1)
         _                                 -> tkErr $ "Unexpected " ++ showBeginning bs ++ ", expecting , or }"
 
     -- key of record (after double quote)
@@ -97,7 +97,7 @@
     goRK' :: Text -> Parser TkRecord k
     goRK' t (skipSpace -> bs) k = case BS.uncons bs of
         Nothing               -> tkErrEOF ":"
-        Just (W8_COLON, !bs3) -> TkPair (Key.fromText t) $ goT bs3 $ \bs4 -> goR1 bs4 k
+        Just (W8.COLON, !bs3) -> TkPair (Key.fromText t) $ goT bs3 $ \bs4 -> goR1 bs4 k
         Just _                -> tkErrBS bs ":"
 
 stripPrefix :: ByteString -> Int -> ByteString -> Maybe ByteString
@@ -187,27 +187,27 @@
     state_start !bs = case BS.uncons bs of
         Nothing                      -> errEnd
         Just (w8, bs')
-            | W8_0 < w8, w8 <= W8_9  -> state_i1 1 bs'
-            | W8_0 == w8             -> state_after0 bs'
-            | otherwise              -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
+            | W8.DIGIT_0 < w8, w8 <= W8.DIGIT_9 -> state_i1 1 bs'
+            | W8.DIGIT_0 == w8                  -> state_after0 bs'
+            | otherwise                         -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
 
     state_after0 :: ByteString -> r
     state_after0 !bs = case BS.uncons bs of
         Nothing                         -> kont (NumInteger 0) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> err "Number literal with leading zero"
-            | W8_DOT == w8              -> go_dec 0 bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci 0 0 bs'
-            | otherwise                 -> kont (NumInteger 0) bs
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9   -> err "Number literal with leading zero"
+            | W8.PERIOD == w8                      -> go_dec 0 bs'
+            | W8.LOWER_E == w8 || W8.UPPER_E == w8 -> go_sci 0 0 bs'
+            | otherwise                            -> kont (NumInteger 0) bs
 
     state_i1 :: Int -> ByteString -> r
     state_i1 !n !bs = case BS.uncons bs of
         Nothing                         -> kont (NumInteger int) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> state_i1 (n + 1) bs'
-            | W8_DOT == w8              -> go_dec int bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci int 0 bs'
-            | otherwise                 -> kont (NumInteger int) bs
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9   -> state_i1 (n + 1) bs'
+            | W8.PERIOD == w8                      -> go_dec int bs'
+            | W8.LOWER_E == w8 || W8.UPPER_E == w8 -> go_sci int 0 bs'
+            | otherwise                            -> kont (NumInteger int) bs
       where
         int = byteStringToInteger (BS.Unsafe.unsafeTake n bs0)
 
@@ -215,16 +215,16 @@
     go_dec !int !bs1 = case BS.uncons bs1 of
         Nothing                       -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> state_dec 1 bs'
-            | otherwise               -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9 -> state_dec 1 bs'
+            | otherwise                          -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
       where
         state_dec :: Int -> ByteString -> r
         state_dec !n !bs = case BS.uncons bs of
             Nothing                         -> kont (NumDecimal dec) bs
             Just (w8, bs')
-                | W8_0 <= w8, w8 <= W8_9    -> state_dec (n + 1) bs'
-                | W8_e == w8 || W8_E == w8  -> go_sci coef (negate n) bs'
-                | otherwise                 -> kont (NumDecimal dec) bs
+                | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9    -> state_dec (n + 1) bs'
+                | W8.LOWER_E == w8 || W8.UPPER_E == w8  -> go_sci coef (negate n) bs'
+                | otherwise                             -> kont (NumDecimal dec) bs
           where
             frac = byteStringToInteger (BS.Unsafe.unsafeTake n bs1)
             coef = int * 10 ^ n + frac
@@ -234,25 +234,25 @@
     go_sci !coef !exp10 !bs2 = case BS.uncons bs2 of
         Nothing                       -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 1 bs'
-            | W8_PLUS == w8           -> case BS.uncons bs' of
-                Nothing               -> errEnd
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9 -> go_sci_pos coef exp10 bs2 1 bs'
+            | W8.PLUS == w8                      -> case BS.uncons bs' of
+                Nothing                          -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_pos coef exp10 bs' 1 bs''
-                    | otherwise       ->  errUnx w8'
-            | W8_MINUS == w8          -> case BS.uncons bs' of
+                    | W8.DIGIT_0 <= w8', w8' <= W8.DIGIT_9 -> go_sci_pos coef exp10 bs' 1 bs''
+                    | otherwise                            -> errUnx w8'
+            | W8.HYPHEN == w8         -> case BS.uncons bs' of
                 Nothing               -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_neg coef exp10 bs' 1 bs''
-                    | otherwise       ->  errUnx w8'
-            | otherwise               -> errUnx w8
+                    | W8.DIGIT_0 <= w8', w8' <= W8.DIGIT_9 -> go_sci_neg coef exp10 bs' 1 bs''
+                    | otherwise                            -> errUnx w8'
+            | otherwise                                    -> errUnx w8
 
     go_sci_pos :: Integer -> Int -> ByteString -> Int -> ByteString -> r
     go_sci_pos !coef !exp10 !bs2 !n !bs = case BS.uncons bs of
         Nothing                       -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 (n + 1) bs'
-            | otherwise               -> kont (NumScientific sci) bs
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9 -> go_sci_pos coef exp10 bs2 (n + 1) bs'
+            | otherwise                          -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (byteStringToInteger (BS.Unsafe.unsafeTake n bs2))
         sci = Sci.scientific coef (exp10 + exp10')
@@ -261,7 +261,7 @@
     go_sci_neg !coef !exp10 !bs2 !n !bs = case BS.uncons bs of
         Nothing                       -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
             | otherwise               -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (byteStringToInteger (BS.Unsafe.unsafeTake n bs2))
diff --git a/src/Data/Aeson/Decoding/ByteString/Lazy.hs b/src/Data/Aeson/Decoding/ByteString/Lazy.hs
--- a/src/Data/Aeson/Decoding/ByteString/Lazy.hs
+++ b/src/Data/Aeson/Decoding/ByteString/Lazy.hs
@@ -18,12 +18,12 @@
 import qualified Data.ByteString              as BS
 import qualified Data.ByteString.Lazy         as LBS
 import qualified Data.Scientific              as Sci
+import qualified Data.Word8.Patterns          as W8
 
 import           Data.Aeson.Decoding.Internal
 import           Data.Aeson.Decoding.Tokens
 import           Data.Aeson.Internal.Text     (unsafeDecodeASCII)
 import           Data.Aeson.Internal.Unescape (unescapeText)
-import           Data.Aeson.Internal.Word8
 
 -- | Lex (and parse) lazy 'ByteString' into 'Tokens' stream.
 --
@@ -42,17 +42,17 @@
         -> ByteString         -- whole input, needed for number parsing
         -> (ByteString -> k)  -- continuation
         -> Tokens k String
-    tokenCase W8_OPEN_CURLY   !bs !_   k      = TkRecordOpen (goR bs k)
-    tokenCase W8_OPEN_SQUARE   bs  _   k      = TkArrayOpen (goA bs k)
-    tokenCase W8_DOUBLE_QUOTE  bs  _   k      = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
-    tokenCase W8_MINUS         bs  _   k      = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
+    tokenCase W8.LEFT_CURLY   !bs !_   k      = TkRecordOpen (goR bs k)
+    tokenCase W8.LEFT_SQUARE   bs  _   k      = TkArrayOpen (goA bs k)
+    tokenCase W8.DOUBLE_QUOTE  bs  _   k      = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
+    tokenCase W8.HYPHEN        bs  _   k      = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
     tokenCase w                _   wbs k
-        | W8_0 <= w, w <= W8_9                = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
-    tokenCase W8_n             bs  _   k
+        | W8.DIGIT_0 <= w, w <= W8.DIGIT_9    = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
+    tokenCase W8.LOWER_N       bs  _   k
         | Just bs1 <- stripPrefix "ull" 3 bs  = TkLit LitNull (k bs1)
-    tokenCase W8_t             bs  _   k
+    tokenCase W8.LOWER_T       bs  _   k
         | Just bs1 <- stripPrefix "rue" 3 bs  = TkLit LitTrue (k bs1)
-    tokenCase W8_f             bs  _   k
+    tokenCase W8.LOWER_F       bs  _   k
         | Just bs1 <- stripPrefix "alse" 4 bs = TkLit LitFalse (k bs1)
     tokenCase _                _   wbs _      = tkErr $ "Unexpected " ++ showBeginning wbs ++ ", expecting JSON value"
 
@@ -60,33 +60,33 @@
     goA :: Parser TkArray k
     goA (skipSpace -> bs) k = case LBS.uncons bs of
         Nothing         -> tkErrEOF "JSON value or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W8.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
         Just (w,  !bs1) -> TkItem $ tokenCase w bs1 bs $ \bs2 -> goA1 bs2 k
 
     goA1 :: Parser TkArray k
     goA1 (skipSpace -> bs) k = case LBS.uncons bs of
         Nothing                      -> tkErrEOF ", or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
-        Just (W8_COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
+        Just (W8.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W8.COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
         _                            -> tkErrBS bs ", or ]"
 
     -- Record
     goR :: Parser TkRecord k
     goR (skipSpace -> bs) k = case LBS.uncons bs of
         Nothing                       -> tkErrEOF "record key literal or }"
-        Just (W8_DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
-        Just (W8_CLOSE_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
+        Just (W8.DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
+        Just (W8.RIGHT_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
         Just _                        -> tkErrBS bs "record key literal or }"
 
     -- after record pair, expecting ," or }
     goR1 :: Parser TkRecord k
     goR1 (skipSpace -> bs) k = case LBS.uncons bs of
         Nothing                           -> tkErr "Unexpected end-of-input, expecting , or }"
-        Just (W8_COMMA, !bs1) -> case LBS.uncons (skipSpace bs1) of
+        Just (W8.COMMA, !bs1) -> case LBS.uncons (skipSpace bs1) of
             Nothing                      -> tkErrEOF "key literal"
-            Just (W8_DOUBLE_QUOTE, !bs2) -> goRK bs2 k
+            Just (W8.DOUBLE_QUOTE, !bs2) -> goRK bs2 k
             Just _                       -> tkErrBS bs "key literal"
-        Just (W8_CLOSE_CURLY, !bs1)       -> TkRecordEnd (k bs1)
+        Just (W8.RIGHT_CURLY, !bs1)       -> TkRecordEnd (k bs1)
         _                                 -> tkErr $ "Unexpected " ++ showBeginning bs ++ ", expecting , or }"
 
     -- key of record (after double quote)
@@ -97,7 +97,7 @@
     goRK' :: Text -> Parser TkRecord k
     goRK' t (skipSpace -> bs) k = case LBS.uncons bs of
         Nothing               -> tkErrEOF ":"
-        Just (W8_COLON, !bs3) -> TkPair (Key.fromText t) $ goT bs3 $ \bs4 -> goR1 bs4 k
+        Just (W8.COLON, !bs3) -> TkPair (Key.fromText t) $ goT bs3 $ \bs4 -> goR1 bs4 k
         Just _                -> tkErrBS bs ":"
 
 stripPrefix :: ByteString -> Int -> ByteString -> Maybe ByteString
@@ -193,27 +193,27 @@
     state_start !bs = case LBS.uncons bs of
         Nothing                      -> errEnd
         Just (w8, bs')
-            | W8_0 < w8, w8 <= W8_9  -> state_i1 1 bs'
-            | W8_0 == w8             -> state_after0 bs'
+            | W8.DIGIT_0 < w8, w8 <= W8.DIGIT_9  -> state_i1 1 bs'
+            | W8.DIGIT_0 == w8             -> state_after0 bs'
             | otherwise              -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
 
     state_after0 :: ByteString -> r
     state_after0 !bs = case LBS.uncons bs of
         Nothing                         -> kont (NumInteger 0) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> err "Number literal with leading zero"
-            | W8_DOT == w8              -> go_dec 0 bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci 0 0 bs'
-            | otherwise                 -> kont (NumInteger 0) bs
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9   -> err "Number literal with leading zero"
+            | W8.PERIOD == w8                      -> go_dec 0 bs'
+            | W8.LOWER_E == w8 || W8.UPPER_E == w8 -> go_sci 0 0 bs'
+            | otherwise                            -> kont (NumInteger 0) bs
 
     state_i1 :: Int -> ByteString -> r
     state_i1 !n !bs = case LBS.uncons bs of
         Nothing                         -> kont (NumInteger int) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> state_i1 (n + 1) bs'
-            | W8_DOT == w8              -> go_dec int bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci int 0 bs'
-            | otherwise                 -> kont (NumInteger int) bs
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9   -> state_i1 (n + 1) bs'
+            | W8.PERIOD == w8                      -> go_dec int bs'
+            | W8.LOWER_E == w8 || W8.UPPER_E == w8 -> go_sci int 0 bs'
+            | otherwise                            -> kont (NumInteger int) bs
       where
         int = byteStringToInteger (lbsTake n bs0)
 
@@ -221,16 +221,16 @@
     go_dec !int !bs1 = case LBS.uncons bs1 of
         Nothing                       -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> state_dec 1 bs'
-            | otherwise               -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9 -> state_dec 1 bs'
+            | otherwise                          -> err $ "Unexpected " ++ show w8 ++ " while parsing number literal"
       where
         state_dec :: Int -> ByteString -> r
         state_dec !n !bs = case LBS.uncons bs of
             Nothing                         -> kont (NumDecimal dec) bs
             Just (w8, bs')
-                | W8_0 <= w8, w8 <= W8_9    -> state_dec (n + 1) bs'
-                | W8_e == w8 || W8_E == w8  -> go_sci coef (negate n) bs'
-                | otherwise                 -> kont (NumDecimal dec) bs
+                | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9   -> state_dec (n + 1) bs'
+                | W8.LOWER_E == w8 || W8.UPPER_E == w8 -> go_sci coef (negate n) bs'
+                | otherwise                            -> kont (NumDecimal dec) bs
           where
             frac = byteStringToInteger (lbsTake n bs1)
             coef = int * 10 ^ n + frac
@@ -240,16 +240,16 @@
     go_sci !coef !exp10 !bs2 = case LBS.uncons bs2 of
         Nothing                       -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 1 bs'
-            | W8_PLUS == w8           -> case LBS.uncons bs' of
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9  -> go_sci_pos coef exp10 bs2 1 bs'
+            | W8.PLUS == w8           -> case LBS.uncons bs' of
                 Nothing               -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_pos coef exp10 bs' 1 bs''
+                    | W8.DIGIT_0 <= w8', w8' <= W8.DIGIT_9  -> go_sci_pos coef exp10 bs' 1 bs''
                     | otherwise       ->  errUnx w8'
-            | W8_MINUS == w8          -> case LBS.uncons bs' of
+            | W8.HYPHEN == w8         -> case LBS.uncons bs' of
                 Nothing               -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_neg coef exp10 bs' 1 bs''
+                    | W8.DIGIT_0 <= w8', w8' <= W8.DIGIT_9  -> go_sci_neg coef exp10 bs' 1 bs''
                     | otherwise       ->  errUnx w8'
             | otherwise               -> errUnx w8
 
@@ -257,7 +257,7 @@
     go_sci_pos !coef !exp10 !bs2 !n !bs = case LBS.uncons bs of
         Nothing                       -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 (n + 1) bs'
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9  -> go_sci_pos coef exp10 bs2 (n + 1) bs'
             | otherwise               -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (byteStringToInteger (lbsTake n bs2))
@@ -267,7 +267,7 @@
     go_sci_neg !coef !exp10 !bs2 !n !bs = case LBS.uncons bs of
         Nothing                       -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
+            | W8.DIGIT_0 <= w8, w8 <= W8.DIGIT_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
             | otherwise               -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (byteStringToInteger (lbsTake n bs2))
diff --git a/src/Data/Aeson/Decoding/Text.hs b/src/Data/Aeson/Decoding/Text.hs
--- a/src/Data/Aeson/Decoding/Text.hs
+++ b/src/Data/Aeson/Decoding/Text.hs
@@ -24,9 +24,9 @@
 import           Data.Aeson.Internal.UnescapeFromText (unescapeFromText)
 
 #if MIN_VERSION_text(2,0,0)
-import           Data.Aeson.Internal.Word8
+import qualified Data.Word8.Patterns as W
 #else
-import           Data.Aeson.Internal.Word16
+import qualified Data.Word16.Patterns as W
 #endif
 
 #if MIN_VERSION_text(2,0,0)
@@ -53,51 +53,50 @@
         -> Text               -- whole input, needed for number parsing
         -> (Text -> k)        -- continuation
         -> Tokens k String
-    tokenCase W8_OPEN_CURLY   !bs !_   k      = TkRecordOpen (goR bs k)
-    tokenCase W8_OPEN_SQUARE   bs  _   k      = TkArrayOpen (goA bs k)
-    tokenCase W8_DOUBLE_QUOTE  bs  _   k      = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
-    tokenCase W8_MINUS         bs  _   k      = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
+    tokenCase W.LEFT_CURLY   !bs !_   k       = TkRecordOpen (goR bs k)
+    tokenCase W.LEFT_SQUARE   bs  _   k       = TkArrayOpen (goA bs k)
+    tokenCase W.DOUBLE_QUOTE  bs  _   k       = scanStringLiteral (\t bs' -> TkText t (k bs')) tkErr bs
+    tokenCase W.HYPHEN        bs  _   k       = scanNumberLiteral (\n bs' -> TkNumber (negateNumber n) (k bs')) tkErr bs
     tokenCase w                _   wbs k
-        | W8_0 <= w, w <= W8_9                = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
-    tokenCase W8_n             bs  _   k
+        | W.DIGIT_0 <= w, w <= W.DIGIT_9      = scanNumberLiteral (\n bs' -> TkNumber n (k bs')) tkErr wbs
+    tokenCase W.LOWER_N       bs  _   k
         | Just bs1 <- stripPrefix "ull" 3 bs  = TkLit LitNull (k bs1)
-    tokenCase W8_t             bs  _   k
+    tokenCase W.LOWER_T       bs  _   k
         | Just bs1 <- stripPrefix "rue" 3 bs  = TkLit LitTrue (k bs1)
-    tokenCase W8_f             bs  _   k
+    tokenCase W.LOWER_F       bs  _   k
         | Just bs1 <- stripPrefix "alse" 4 bs = TkLit LitFalse (k bs1)
-    tokenCase _                _   wbs _      = tkErr $ "Unexpected " ++ showBeginning wbs ++ ", expecting JSON value"
-
+    tokenCase _          _   wbs _            = tkErr $ "Unexpected " ++ showBeginning wbs ++ ", expecting JSON value"
     -- Array
     goA :: Parser TkArray k
     goA (skipSpace -> bs) k = case unconsPoint bs of
         Nothing         -> tkErrEOF "JSON value or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
         Just (w,  !bs1) -> TkItem $ tokenCase w bs1 bs $ \bs2 -> goA1 bs2 k
 
     goA1 :: Parser TkArray k
     goA1 (skipSpace -> bs) k = case unconsPoint bs of
         Nothing                      -> tkErrEOF ", or ]"
-        Just (W8_CLOSE_SQUARE, !bs1) -> TkArrayEnd (k bs1)
-        Just (W8_COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
+        Just (W.RIGHT_SQUARE, !bs1) -> TkArrayEnd (k bs1)
+        Just (W.COMMA, !bs1)        -> TkItem $ goT bs1 $ \bs2 -> goA1 bs2 k
         _                            -> tkErrBS bs ", or ]"
 
     -- Record
     goR :: Parser TkRecord k
     goR (skipSpace -> bs) k = case unconsPoint bs of
         Nothing                       -> tkErrEOF "record key literal or }"
-        Just (W8_DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
-        Just (W8_CLOSE_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
+        Just (W.DOUBLE_QUOTE,  !bs1) -> goRK bs1 k           -- "
+        Just (W.RIGHT_CURLY, !bs1)   -> TkRecordEnd (k bs1)  -- }
         Just _                        -> tkErrBS bs "record key literal or }"
 
     -- after record pair, expecting ," or }
     goR1 :: Parser TkRecord k
     goR1 (skipSpace -> bs) k = case unconsPoint bs of
         Nothing                           -> tkErr "Unexpected end-of-input, expecting , or }"
-        Just (W8_COMMA, !bs1) -> case unconsPoint (skipSpace bs1) of
+        Just (W.COMMA, !bs1) -> case unconsPoint (skipSpace bs1) of
             Nothing                      -> tkErrEOF "key literal"
-            Just (W8_DOUBLE_QUOTE, !bs2) -> goRK bs2 k
+            Just (W.DOUBLE_QUOTE, !bs2) -> goRK bs2 k
             Just _                       -> tkErrBS bs "key literal"
-        Just (W8_CLOSE_CURLY, !bs1)       -> TkRecordEnd (k bs1)
+        Just (W.RIGHT_CURLY, !bs1)       -> TkRecordEnd (k bs1)
         _                                 -> tkErr $ "Unexpected " ++ showBeginning bs ++ ", expecting , or }"
 
     -- key of record (after double quote)
@@ -196,46 +195,46 @@
 scanNumberLiteral kont err bs0 = state_start bs0 where
     state_start :: Text -> r
     state_start !bs = case unconsPoint bs of
-        Nothing                      -> errEnd
+        Nothing                                   -> errEnd
         Just (w8, bs')
-            | W8_0 < w8, w8 <= W8_9  -> state_i1 1 bs'
-            | W8_0 == w8             -> state_after0 bs'
-            | otherwise              -> errUnx w8
+            | W.DIGIT_0 < w8, w8 <= W.DIGIT_9     -> state_i1 1 bs'
+            | W.DIGIT_0 == w8                     -> state_after0 bs'
+            | otherwise                           -> errUnx w8
 
     state_after0 :: Text -> r
     state_after0 !bs = case unconsPoint bs of
-        Nothing                         -> kont (NumInteger 0) bs
+        Nothing                                   -> kont (NumInteger 0) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> err "Number literal with leading zero"
-            | W8_DOT == w8              -> go_dec 0 bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci 0 0 bs'
-            | otherwise                 -> kont (NumInteger 0) bs
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9    -> err "Number literal with leading zero"
+            | W.PERIOD == w8                      -> go_dec 0 bs'
+            | W.LOWER_E == w8 || W.UPPER_E == w8  -> go_sci 0 0 bs'
+            | otherwise                           -> kont (NumInteger 0) bs
 
     state_i1 :: Int -> Text -> r
     state_i1 !n !bs = case unconsPoint bs of
-        Nothing                         -> kont (NumInteger int) bs
+        Nothing                                   -> kont (NumInteger int) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9    -> state_i1 (n + 1) bs'
-            | W8_DOT == w8              -> go_dec int bs'
-            | W8_e == w8 || W8_E == w8  -> go_sci int 0 bs'
-            | otherwise                 -> kont (NumInteger int) bs
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9    -> state_i1 (n + 1) bs'
+            | W.PERIOD == w8                      -> go_dec int bs'
+            | W.LOWER_E == w8 || W.UPPER_E == w8  -> go_sci int 0 bs'
+            | otherwise                           -> kont (NumInteger int) bs
       where
         int = textToInteger (unsafeTakePoints n bs0)
 
     go_dec :: Integer -> Text -> r
     go_dec !int !bs1 = case unconsPoint bs1 of
-        Nothing                       -> errEnd
+        Nothing                                   -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> state_dec 1 bs'
-            | otherwise               -> errUnx w8
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9    -> state_dec 1 bs'
+            | otherwise                           -> errUnx w8
       where
         state_dec :: Int -> Text -> r
         state_dec !n !bs = case unconsPoint bs of
-            Nothing                         -> kont (NumDecimal dec) bs
+            Nothing                                   -> kont (NumDecimal dec) bs
             Just (w8, bs')
-                | W8_0 <= w8, w8 <= W8_9    -> state_dec (n + 1) bs'
-                | W8_e == w8 || W8_E == w8  -> go_sci coef (negate n) bs'
-                | otherwise                 -> kont (NumDecimal dec) bs
+                | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9    -> state_dec (n + 1) bs'
+                | W.LOWER_E == w8 || W.UPPER_E == w8  -> go_sci coef (negate n) bs'
+                | otherwise                           -> kont (NumDecimal dec) bs
           where
             frac = textToInteger (unsafeTakePoints n bs1)
             coef = int * 10 ^ n + frac
@@ -243,37 +242,37 @@
 
     go_sci :: Integer -> Int -> Text -> r
     go_sci !coef !exp10 !bs2 = case unconsPoint bs2 of
-        Nothing                       -> errEnd
+        Nothing                                           -> errEnd
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 1 bs'
-            | W8_PLUS == w8           -> case unconsPoint bs' of
-                Nothing               -> errEnd
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9            -> go_sci_pos coef exp10 bs2 1 bs'
+            | W.PLUS == w8 -> case unconsPoint bs' of
+                Nothing                                   -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_pos coef exp10 bs' 1 bs''
-                    | otherwise       ->  errUnx w8'
-            | W8_MINUS == w8          -> case unconsPoint bs' of
-                Nothing               -> errEnd
+                    | W.DIGIT_0 <= w8', w8' <= W.DIGIT_9  -> go_sci_pos coef exp10 bs' 1 bs''
+                    | otherwise                           -> errUnx w8'
+            | W.HYPHEN == w8 -> case unconsPoint bs' of
+                Nothing                                   -> errEnd
                 Just (w8', bs'')
-                    | W8_0 <= w8', w8' <= W8_9  -> go_sci_neg coef exp10 bs' 1 bs''
-                    | otherwise       ->  errUnx w8'
-            | otherwise               -> errUnx w8
+                    | W.DIGIT_0 <= w8', w8' <= W.DIGIT_9  -> go_sci_neg coef exp10 bs' 1 bs''
+                    | otherwise                           -> errUnx w8'
+            | otherwise                                   -> errUnx w8
 
     go_sci_pos :: Integer -> Int -> Text -> Int -> Text -> r
     go_sci_pos !coef !exp10 !bs2 !n !bs = case unconsPoint bs of
-        Nothing                       -> kont (NumScientific sci) bs
+        Nothing                                 -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_pos coef exp10 bs2 (n + 1) bs'
-            | otherwise               -> kont (NumScientific sci) bs
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9  -> go_sci_pos coef exp10 bs2 (n + 1) bs'
+            | otherwise                         -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (textToInteger (unsafeTakePoints n bs2))
         sci = Sci.scientific coef (exp10 + exp10')
 
     go_sci_neg :: Integer -> Int -> Text -> Int -> Text -> r
     go_sci_neg !coef !exp10 !bs2 !n !bs = case unconsPoint bs of
-        Nothing                       -> kont (NumScientific sci) bs
+        Nothing                                 -> kont (NumScientific sci) bs
         Just (w8, bs')
-            | W8_0 <= w8, w8 <= W8_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
-            | otherwise               -> kont (NumScientific sci) bs
+            | W.DIGIT_0 <= w8, w8 <= W.DIGIT_9  -> go_sci_neg coef exp10 bs2 (n + 1) bs'
+            | otherwise                         -> kont (NumScientific sci) bs
       where
         exp10' = fromInteger (textToInteger (unsafeTakePoints n bs2))
         sci = Sci.scientific coef (exp10 - exp10')
diff --git a/src/Data/Aeson/Internal/Word16.hs b/src/Data/Aeson/Internal/Word16.hs
deleted file mode 100644
--- a/src/Data/Aeson/Internal/Word16.hs
+++ /dev/null
@@ -1,76 +0,0 @@
-{-# LANGUAGE PatternSynonyms #-}
--- | This is s/Word8/Word16/g copy of .Word8 module.
--- This module is used for low-bit working with text <2 (UTF-16)
-module Data.Aeson.Internal.Word16 where
-
-import Data.Word (Word16)
-
--------------------------------------------------------------------------------
--- Word16 ASCII codes as patterns
--------------------------------------------------------------------------------
-
--- GHC-8.0 doesn't support giving multiple pattern synonyms type signature at once
-
--- spaces
-pattern W8_SPACE :: Word16
-pattern W8_NL    :: Word16
-pattern W8_CR    :: Word16
-pattern W8_TAB   :: Word16
-
-pattern W8_SPACE = 0x20
-pattern W8_NL    = 0x0a
-pattern W8_CR    = 0x0d
-pattern W8_TAB   = 0x09
-
--- punctuation
-pattern W8_BACKSLASH    :: Word16
-pattern W8_DOUBLE_QUOTE :: Word16
-pattern W8_DOT          :: Word16
-pattern W8_COMMA        :: Word16
-pattern W8_COLON        :: Word16
-
-pattern W8_BACKSLASH    = 92
-pattern W8_COMMA        = 44
-pattern W8_DOT          = 46
-pattern W8_DOUBLE_QUOTE = 34
-pattern W8_COLON        = 58
-
--- parentheses
-pattern W8_CLOSE_CURLY  :: Word16
-pattern W8_CLOSE_SQUARE :: Word16
-pattern W8_OPEN_SQUARE  :: Word16
-pattern W8_OPEN_CURLY   :: Word16
-
-pattern W8_OPEN_CURLY   = 123
-pattern W8_OPEN_SQUARE  = 91
-pattern W8_CLOSE_CURLY  = 125
-pattern W8_CLOSE_SQUARE = 93
-
--- operators
-pattern W8_MINUS :: Word16
-pattern W8_PLUS  :: Word16
-
-pattern W8_PLUS  = 43
-pattern W8_MINUS = 45
-
--- digits
-pattern W8_0 :: Word16
-pattern W8_9 :: Word16
-
-pattern W8_0 = 48
-pattern W8_9 = 57
-
--- lower case
-pattern W8_e :: Word16
-pattern W8_f :: Word16
-pattern W8_n :: Word16
-pattern W8_t :: Word16
-
-pattern W8_e = 101
-pattern W8_f = 102
-pattern W8_n = 110
-pattern W8_t = 116
-
--- upper case
-pattern W8_E :: Word16
-pattern W8_E = 69
diff --git a/src/Data/Aeson/Internal/Word8.hs b/src/Data/Aeson/Internal/Word8.hs
deleted file mode 100644
--- a/src/Data/Aeson/Internal/Word8.hs
+++ /dev/null
@@ -1,74 +0,0 @@
-{-# LANGUAGE PatternSynonyms #-}
-module Data.Aeson.Internal.Word8 where
-
-import Data.Word (Word8)
-
--------------------------------------------------------------------------------
--- Word8 ASCII codes as patterns
--------------------------------------------------------------------------------
-
--- GHC-8.0 doesn't support giving multiple pattern synonyms type signature at once
-
--- spaces
-pattern W8_SPACE :: Word8
-pattern W8_NL    :: Word8
-pattern W8_CR    :: Word8
-pattern W8_TAB   :: Word8
-
-pattern W8_SPACE = 0x20
-pattern W8_NL    = 0x0a
-pattern W8_CR    = 0x0d
-pattern W8_TAB   = 0x09
-
--- punctuation
-pattern W8_BACKSLASH    :: Word8
-pattern W8_DOUBLE_QUOTE :: Word8
-pattern W8_DOT          :: Word8
-pattern W8_COMMA        :: Word8
-pattern W8_COLON        :: Word8
-
-pattern W8_BACKSLASH    = 92
-pattern W8_COMMA        = 44
-pattern W8_DOT          = 46
-pattern W8_DOUBLE_QUOTE = 34
-pattern W8_COLON        = 58
-
--- parentheses
-pattern W8_CLOSE_CURLY  :: Word8
-pattern W8_CLOSE_SQUARE :: Word8
-pattern W8_OPEN_SQUARE  :: Word8
-pattern W8_OPEN_CURLY   :: Word8
-
-pattern W8_OPEN_CURLY   = 123
-pattern W8_OPEN_SQUARE  = 91
-pattern W8_CLOSE_CURLY  = 125
-pattern W8_CLOSE_SQUARE = 93
-
--- operators
-pattern W8_MINUS :: Word8
-pattern W8_PLUS  :: Word8
-
-pattern W8_PLUS  = 43
-pattern W8_MINUS = 45
-
--- digits
-pattern W8_0 :: Word8
-pattern W8_9 :: Word8
-
-pattern W8_0 = 48
-pattern W8_9 = 57
-
--- lower case
-pattern W8_e :: Word8
-pattern W8_f :: Word8
-pattern W8_n :: Word8
-pattern W8_t :: Word8
-
-pattern W8_e = 101
-pattern W8_f = 102
-pattern W8_n = 110
-pattern W8_t = 116
-
--- upper case
-pattern W8_E :: Word8
-pattern W8_E = 69
diff --git a/src/Data/Aeson/RFC8785.hs b/src/Data/Aeson/RFC8785.hs
--- a/src/Data/Aeson/RFC8785.hs
+++ b/src/Data/Aeson/RFC8785.hs
@@ -13,7 +13,6 @@
 import Data.Aeson.Encoding
 import Data.Aeson.Encoding.Internal
 import Data.Aeson.Internal.Prelude
-import Data.Aeson.Internal.Word8
 
 import qualified Data.Aeson.Key as Key
 import qualified Data.Aeson.KeyMap as KM
@@ -24,6 +23,7 @@
 import qualified Data.Scientific as Sci
 import qualified Data.Text.Encoding as TE
 import qualified Data.Vector as V
+import qualified Data.Word8.Patterns as W8
 
 -- $setup
 -- >>> import Data.Aeson
@@ -94,8 +94,8 @@
 -- RFC8785 Appendix D says "don't use bignums".
 canonicalNumber :: Scientific -> Encoding
 canonicalNumber m = case compare m 0 of
-    EQ -> Encoding (B.word8 W8_0)
-    LT -> Encoding (B.word8 W8_MINUS <> fromEncoding (canonicalNumber' (negate m)))
+    EQ -> Encoding (B.word8 W8.DIGIT_0)
+    LT -> Encoding (B.word8 W8.HYPHEN <> fromEncoding (canonicalNumber' (negate m)))
     GT -> canonicalNumber' m
 
 -- input: Positive number
@@ -104,36 +104,36 @@
     | k <= n, n <= 21
     = Encoding $
         BP.primMapListFixed BP.word8 ds <>
-        BP.primMapListFixed BP.word8 (replicate (n - k) W8_0)
+        BP.primMapListFixed BP.word8 (replicate (n - k) W8.DIGIT_0)
 
     | 0 < n, n <= 21
     , let (pfx, sfx) = splitAt n ds
     = Encoding $
         BP.primMapListFixed BP.word8 pfx <>
-        B.word8 W8_DOT <>
+        B.word8 W8.PERIOD <>
         BP.primMapListFixed BP.word8 sfx
 
     | -6 < n, n <= 0
     = Encoding $
-        B.word8 W8_0 <>
-        B.word8 W8_DOT <>
-        BP.primMapListFixed BP.word8 (replicate (negate n) W8_0) <>
+        B.word8 W8.DIGIT_0 <>
+        B.word8 W8.PERIOD <>
+        BP.primMapListFixed BP.word8 (replicate (negate n) W8.DIGIT_0) <>
         BP.primMapListFixed BP.word8 ds
 
     | k == 1, [d] <- ds
     = Encoding $
         B.word8 d <>
-        B.word8 W8_e <>
-        B.word8 (if (n - 1) >= 0 then W8_PLUS else W8_MINUS) <>
+        B.word8 W8.LOWER_E <>
+        B.word8 (if (n - 1) >= 0 then W8.PLUS else W8.HYPHEN) <>
         BP.primMapListFixed BP.word8 (integerToDecimalDigits (abs (toInteger n - 1)))
 
     | (d:ds') <- ds
     = Encoding $
         B.word8 d <>
-        B.word8 W8_DOT <>
+        B.word8 W8.PERIOD <>
         BP.primMapListFixed BP.word8 ds' <>
-        B.word8 W8_e <>
-        B.word8 (if (n - 1) >= 0 then W8_PLUS else W8_MINUS) <>
+        B.word8 W8.LOWER_E <>
+        B.word8 (if (n - 1) >= 0 then W8.PLUS else W8.HYPHEN) <>
         BP.primMapListFixed BP.word8 (integerToDecimalDigits (abs (toInteger n - 1)))
 
     | otherwise
@@ -166,4 +166,4 @@
 integerToDecimalDigits = go [] where
     go acc 0 = acc
     go acc i = case quotRemInteger i 10 of
-        (# q, r #) -> go (d:acc) q where !d = fromIntegral r + W8_0
+        (# q, r #) -> go (d:acc) q where !d = fromIntegral r + W8.DIGIT_0
diff --git a/src/Data/Aeson/Types/FromJSON.hs b/src/Data/Aeson/Types/FromJSON.hs
--- a/src/Data/Aeson/Types/FromJSON.hs
+++ b/src/Data/Aeson/Types/FromJSON.hs
@@ -865,7 +865,7 @@
 (.:!) = explicitParseFieldMaybe' parseJSON
 
 -- | Retrieve the value associated with the given key of an 'Object'.
--- If the key is not present and the 'omittedField' is @'Just' x@ for some @x@,
+-- If the key is not present or the field is @null@ and the 'omittedField' is @'Just' x@ for some @x@,
 -- the result will be that @x@.
 --
 -- @since 2.2.0.0
@@ -873,7 +873,7 @@
 (.:?=) = explicitParseFieldOmit omittedField parseJSON
 
 -- | Retrieve the value associated with the given key of an 'Object'.
--- If the key is not present or the field is @null@ and the 'omittedField' is @'Just' x@ for some @x@,
+-- If the key is not present and the 'omittedField' is @'Just' x@ for some @x@,
 -- the result will be that @x@.
 --
 -- This differs from '.:?=' by attempting to parse 'Null' the same as any
