diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
deleted file mode 100644
--- a/CHANGELOG.markdown
+++ /dev/null
@@ -1,7 +0,0 @@
-# Change log
-
-Derulo uses [Semantic Versioning][].
-The change log is available through the [releases on GitHub][].
-
-[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
-[releases on GitHub]: https://github.com/tfausak/derulo/releases
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -1,10 +1,10 @@
 # Derulo
 
-[![Build badge]][build status]
+[![Travis CI](https://travis-ci.org/tfausak/derulo.svg?branch=master)](https://travis-ci.org/tfausak/derulo)
+[![Hackage](https://img.shields.io/hackage/v/derulo)](https://hackage.haskell.org/package/derulo)
+[![Stackage](https://www.stackage.org/package/derulo/badge/nightly?label=stackage)](https://www.stackage.org/package/derulo)
 
 Derulo is a Haskell library and executable that parses and renders JSON simply.
 It has extensive documentation [on Hackage][].
 
-[Build badge]: https://travis-ci.org/tfausak/derulo.svg?branch=master
-[build status]: https://travis-ci.org/tfausak/derulo
 [on Hackage]: https://hackage.haskell.org/package/derulo
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-import qualified Distribution.Simple as Cabal
-
-main :: IO ()
-main = Cabal.defaultMain
diff --git a/derulo.cabal b/derulo.cabal
--- a/derulo.cabal
+++ b/derulo.cabal
@@ -1,71 +1,67 @@
-cabal-version: 1.12
+cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
---
--- see: https://github.com/sol/hpack
---
--- hash: a141501f812d92ada6a2974d9a03a24b2b99a67047d314c9c6eb740cca2eb554
+name: derulo
+version: 1.0.9
 
-name:           derulo
-version:        1.0.8
-synopsis:       Parse and render JSON simply.
-description:    Derulo parses and renders JSON simply.
-category:       JSON
-homepage:       https://github.com/tfausak/derulo#readme
-bug-reports:    https://github.com/tfausak/derulo/issues
-maintainer:     Taylor Fausak
-license:        MIT
-license-file:   LICENSE.markdown
-build-type:     Simple
-extra-source-files:
-    CHANGELOG.markdown
-    package.yaml
-    README.markdown
-    stack.yaml
+synopsis: Parse and render JSON simply.
+description: Derulo parses and renders JSON simply.
 
+build-type: Simple
+category: JSON
+extra-source-files: README.markdown
+license-file: LICENSE.markdown
+license: MIT
+maintainer: Taylor Fausak
+
 source-repository head
   type: git
   location: https://github.com/tfausak/derulo
 
+common basics
+  default-language: Haskell2010
+  ghc-options:
+    -Weverything
+    -Wno-all-missed-specialisations
+    -Wno-implicit-prelude
+    -Wno-missing-exported-signatures
+    -Wno-missing-import-lists
+    -Wno-safe
+    -Wno-unsafe
+
+  if impl(ghc >= 8.8)
+    ghc-options:
+      -Wno-missing-deriving-strategies
+
+  if impl(ghc >= 8.10)
+    ghc-options:
+      -Wno-missing-safe-haskell-mode
+      -Wno-prepositive-qualified-module
+
 library
-  exposed-modules:
-      Derulo
-  other-modules:
-      Paths_derulo
-  hs-source-dirs:
-      library
-  ghc-options: -Weverything -Wno-implicit-prelude -Wno-safe -Wno-unsafe
+  import: basics
+
   build-depends:
-      base >=4.9.0 && <4.15
-  if impl(ghc >= 8.8.1)
-    ghc-options: -Wno-missing-deriving-strategies
-  default-language: Haskell2010
+    base >= 4.9.0 && < 4.15
+  default-language: Haskell98
+  exposed-modules: Derulo
+  hs-source-dirs: src/lib
 
 executable derulo
-  main-is: Main.hs
-  other-modules:
-      Paths_derulo
-  hs-source-dirs:
-      executables
-  ghc-options: -Weverything -Wno-implicit-prelude -Wno-safe -Wno-unsafe -rtsopts -threaded
+  import: basics
+
   build-depends:
-      base >=4.9.0 && <4.15
-    , derulo
-  if impl(ghc >= 8.8.1)
-    ghc-options: -Wno-missing-deriving-strategies
-  default-language: Haskell2010
+    base -any,
+    derulo -any
+  hs-source-dirs: src/exe
+  main-is: Main.hs
 
 test-suite test
-  type: exitcode-stdio-1.0
-  main-is: Main.hs
-  other-modules:
-      Paths_derulo
-  hs-source-dirs:
-      tests
-  ghc-options: -Weverything -Wno-implicit-prelude -Wno-safe -Wno-unsafe -rtsopts -threaded
+  import: basics
+
   build-depends:
-      base >=4.9.0 && <4.15
-    , doctest >=0.11.0 && <0.17
-  if impl(ghc >= 8.8.1)
-    ghc-options: -Wno-missing-deriving-strategies
-  default-language: Haskell2010
+    base -any
+    , derulo -any
+    , HUnit >= 1.6.0 && < 1.7
+  hs-source-dirs: src/test
+  main-is: Main.hs
+  type: exitcode-stdio-1.0
diff --git a/executables/Main.hs b/executables/Main.hs
deleted file mode 100644
--- a/executables/Main.hs
+++ /dev/null
@@ -1,5 +0,0 @@
-import qualified Data.Maybe as Maybe
-import qualified Derulo
-
-main :: IO ()
-main = interact (Derulo.showJSON . Maybe.fromJust . Derulo.readJSON)
diff --git a/library/Derulo.hs b/library/Derulo.hs
deleted file mode 100644
--- a/library/Derulo.hs
+++ /dev/null
@@ -1,1098 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveGeneric #-}
-
--- | Derulo parses and renders JSON simply. It aims to provide an RFC 7159
--- compliant parser and renderer without incurring any dependencies. It is
--- intended to be used either for learning or in situations where dependencies
--- are unwanted. In normal usage, prefer a faster, more robust library like
--- [Aeson](https://hackage.haskell.org/package/aeson).
---
--- Derulo does not export any identifiers that conflict with the prelude and
--- can be imported unqualified.
---
--- >>> import Derulo
---
--- Use 'readJSON' to parse a 'String' into a 'JSON' value.
---
--- >>> readJSON " null "
--- Just Null
---
--- Use 'showJSON' to render a 'JSON' value as a 'String'.
---
--- >>> showJSON Null
--- "null"
-module Derulo
-  ( JSON(..)
-  , readJSON
-  , showJSON
-  ) where
-
-import qualified Control.Monad as Monad
-import qualified Data.Data as Data
-import qualified Data.Functor as Functor
-import qualified Data.List as List
-import qualified Data.Maybe as Maybe
-import qualified GHC.Generics as Generics
-import qualified Text.ParserCombinators.ReadP as ReadP
-
--- * Types
--- | A JSON value as described by RFC 7159.
-data JSON
-  = Null
-  | Boolean Bool
-  | Number Integer
-           Integer
-  | String String
-  | Array [JSON]
-  | Object [(String, JSON)]
-  deriving (Data.Data, Eq, Generics.Generic, Ord, Read, Show)
-
--- * Parsing
--- | Parses a string as JSON.
---
--- >>> readJSON "null"
--- Just Null
---
--- >>> readJSON "true"
--- Just (Boolean True)
--- >>> readJSON "false"
--- Just (Boolean False)
---
--- >>> readJSON "0e0"
--- Just (Number 0 0)
--- >>> readJSON "12e34"
--- Just (Number 12 34)
--- >>> readJSON "-12e-34"
--- Just (Number (-12) (-34))
---
--- >>> readJSON "\"\""
--- Just (String "")
--- >>> readJSON "\"js\""
--- Just (String "js")
--- >>> readJSON "\"\\\"\\\\\\b\\f\\n\\r\\t\""
--- Just (String "\"\\\b\f\n\r\t")
--- >>> readJSON "\"\\u001f\""
--- Just (String "\US")
---
--- >>> readJSON "[]"
--- Just (Array [])
--- >>> readJSON "[null]"
--- Just (Array [Null])
--- >>> readJSON "[true,false]"
--- Just (Array [Boolean True,Boolean False])
---
--- >>> readJSON "{}"
--- Just (Object [])
--- >>> readJSON "{\"\":null}"
--- Just (Object [("",Null)])
--- >>> readJSON "{\"t\":true,\"f\":false}"
--- Just (Object [("t",Boolean True),("f",Boolean False)])
-readJSON :: String -> Maybe JSON
-readJSON string = runParser pJSON string
-
-pJSON :: ReadP.ReadP JSON
-pJSON = do
-  pWhitespaces
-  value <- pValue
-  ReadP.eof
-  pure value
-
-pValue :: ReadP.ReadP JSON
-pValue = ReadP.choice [pNull, pBoolean, pNumber, pString, pArray, pObject]
-
-pNull :: ReadP.ReadP JSON
-pNull = do
-  pSymbol "null"
-  pure Null
-
-pBoolean :: ReadP.ReadP JSON
-pBoolean = pTrue ReadP.+++ pFalse
-
-pTrue :: ReadP.ReadP JSON
-pTrue = do
-  pSymbol "true"
-  pure (Boolean True)
-
-pFalse :: ReadP.ReadP JSON
-pFalse = do
-  pSymbol "false"
-  pure (Boolean False)
-
-pNumber :: ReadP.ReadP JSON
-pNumber = do
-  integer <- pInteger
-  (fraction, precision) <- ReadP.option (0, 0) pFraction
-  power <- ReadP.option 0 pPower
-  pWhitespaces
-  let mantissa = integer * 10 ^ precision + negateIf (integer <= 0) fraction
-  let magnitude = power - precision
-  pure (Number mantissa magnitude)
-
-pInteger :: ReadP.ReadP Integer
-pInteger = pZero ReadP.+++ pNonZero
-
-pZero :: ReadP.ReadP Integer
-pZero = do
-  ReadP.optional (ReadP.char '-')
-  Functor.void (ReadP.char '0')
-  pure 0
-
-pNonZero :: ReadP.ReadP Integer
-pNonZero = do
-  sign <- ReadP.option '+' (ReadP.char '-')
-  first <- ReadP.satisfy isNonZeroDigit
-  rest <- ReadP.munch isDecimalDigit
-  case fromDecimal (first : rest) of
-    Nothing -> ReadP.pfail
-    Just nonZero -> pure (negateIf (sign == '-') nonZero)
-
-pFraction :: ReadP.ReadP (Integer, Integer)
-pFraction = do
-  Functor.void (ReadP.char '.')
-  digits <- ReadP.munch1 isDecimalDigit
-  case fromDecimal digits of
-    Nothing -> ReadP.pfail
-    Just fraction -> pure (fraction, List.genericLength digits)
-
-pPower :: ReadP.ReadP Integer
-pPower = do
-  Functor.void (ReadP.char 'E' ReadP.+++ ReadP.char 'e')
-  sign <- ReadP.option '+' (ReadP.char '+' ReadP.+++ ReadP.char '-')
-  digits <- ReadP.munch1 isDecimalDigit
-  case fromDecimal digits of
-    Nothing -> ReadP.pfail
-    Just magnitude -> pure (negateIf (sign == '-') magnitude)
-
-pString :: ReadP.ReadP JSON
-pString = do
-  string <-
-    ReadP.between
-      (ReadP.char '"')
-      (ReadP.char '"')
-      (do characters <- ReadP.many pCharacter
-          pure (String characters))
-  pWhitespaces
-  pure string
-
-pCharacter :: ReadP.ReadP Char
-pCharacter = pLiteral ReadP.+++ pEscape
-
-pLiteral :: ReadP.ReadP Char
-pLiteral = ReadP.satisfy isLiteral
-
-pEscape :: ReadP.ReadP Char
-pEscape = do
-  Functor.void (ReadP.char '\\')
-  escape <- ReadP.get
-  case escape of
-    '"' -> pure '"'
-    '/' -> pure '/'
-    '\\' -> pure '\\'
-    'b' -> pure '\b'
-    'f' -> pure '\f'
-    'n' -> pure '\n'
-    'r' -> pure '\r'
-    't' -> pure '\t'
-    'u' -> do
-      digits <- ReadP.count 4 (ReadP.satisfy isHexadecimalDigit)
-      case fromHexadecimal digits of
-        Nothing -> ReadP.pfail
-        Just point -> pure (toEnum (fromIntegral point))
-    _ -> ReadP.pfail
-
-pArray :: ReadP.ReadP JSON
-pArray =
-  ReadP.between
-    (pSymbol "[")
-    (pSymbol "]")
-    (do values <- ReadP.sepBy pValue (pSymbol ",")
-        pure (Array values))
-
-pObject :: ReadP.ReadP JSON
-pObject =
-  ReadP.between
-    (pSymbol "{")
-    (pSymbol "}")
-    (do pairs <- ReadP.sepBy pPair (pSymbol ",")
-        pure (Object pairs))
-
-pPair :: ReadP.ReadP (String, JSON)
-pPair = do
-  String key <- pString
-  pSymbol ":"
-  value <- pValue
-  pure (key, value)
-
--- * Rendering
--- | Renders JSON as a string.
---
--- >>> showJSON Null
--- "null"
---
--- >>> showJSON (Boolean True)
--- "true"
--- >>> showJSON (Boolean False)
--- "false"
---
--- >>> showJSON (Number 0 0)
--- "0e0"
--- >>> showJSON (Number 12 34)
--- "12e34"
--- >>> showJSON (Number (-12) (-34))
--- "-12e-34"
---
--- >>> showJSON (String "")
--- "\"\""
--- >>> showJSON (String "js")
--- "\"js\""
--- >>> showJSON (String "\"\\\b\f\n\r\t")
--- "\"\\\"\\\\\\b\\f\\n\\r\\t\""
--- >>> showJSON (String "\x1f")
--- "\"\\u001f\""
---
--- >>> showJSON (Array [])
--- "[]"
--- >>> showJSON (Array [Null])
--- "[null]"
--- >>> showJSON (Array [Boolean True, Boolean False])
--- "[true,false]"
---
--- >>> showJSON (Object [])
--- "{}"
--- >>> showJSON (Object [("", Null)])
--- "{\"\":null}"
--- >>> showJSON (Object [("t", Boolean True), ("f", Boolean False)])
--- "{\"t\":true,\"f\":false}"
-showJSON :: JSON -> String
-showJSON json = sJSON json ""
-
-sJSON :: JSON -> ShowS
-sJSON json =
-  case json of
-    Null -> sNull
-    Boolean boolean -> sBoolean boolean
-    Number mantissa magnitude -> sNumber mantissa magnitude
-    String string -> sString string
-    Array array -> sArray array
-    Object object -> sObject object
-
-sNull :: ShowS
-sNull = showString "null"
-
-sBoolean :: Bool -> ShowS
-sBoolean boolean =
-  if boolean
-    then sTrue
-    else sFalse
-
-sTrue :: ShowS
-sTrue = showString "true"
-
-sFalse :: ShowS
-sFalse = showString "false"
-
-sNumber :: Integer -> Integer -> ShowS
-sNumber mantissa magnitude = shows mantissa . showChar 'e' . shows magnitude
-
-sString :: String -> ShowS
-sString string =
-  sSeparatedBetween (showChar '"') (showChar '"') id sCharacter string
-
-sCharacter :: Char -> ShowS
-sCharacter character =
-  case character of
-    '"' -> showString "\\\""
-    '\\' -> showString "\\\\"
-    '\b' -> showString "\\b"
-    '\f' -> showString "\\f"
-    '\n' -> showString "\\n"
-    '\r' -> showString "\\r"
-    '\t' -> showString "\\t"
-    _ ->
-      if isControl character
-        then showString "\\u" .
-             showString
-               (padLeft
-                  4
-                  '0'
-                  (toHexadecimal (fromIntegral (fromEnum character))))
-        else showChar character
-
-sArray :: [JSON] -> ShowS
-sArray array =
-  sSeparatedBetween (showChar '[') (showChar ']') (showChar ',') sJSON array
-
-sObject :: [(String, JSON)] -> ShowS
-sObject object =
-  sSeparatedBetween (showChar '{') (showChar '}') (showChar ',') sPair object
-
-sPair :: (String, JSON) -> ShowS
-sPair (key, value) = sString key . showChar ':' . sJSON value
-
--- * Helpers
-fromBase :: Integer -> (Char -> Maybe Integer) -> String -> Maybe Integer
-fromBase b f s =
-  Monad.foldM
-    (\n c -> do
-       d <- f c
-       pure (b * n + d))
-    0
-    s
-
-fromDecimal :: String -> Maybe Integer
-fromDecimal s = fromBase 10 fromDecimalDigit s
-
-fromDecimalDigit :: Char -> Maybe Integer
-fromDecimalDigit c =
-  case c of
-    '0' -> Just 0
-    '1' -> Just 1
-    '2' -> Just 2
-    '3' -> Just 3
-    '4' -> Just 4
-    '5' -> Just 5
-    '6' -> Just 6
-    '7' -> Just 7
-    '8' -> Just 8
-    '9' -> Just 9
-    _ -> Nothing
-
-fromHexadecimal :: String -> Maybe Integer
-fromHexadecimal s = fromBase 16 fromHexadecimalDigit s
-
-fromHexadecimalDigit :: Char -> Maybe Integer
-fromHexadecimalDigit c =
-  case c of
-    'A' -> Just 10
-    'B' -> Just 11
-    'C' -> Just 12
-    'D' -> Just 13
-    'E' -> Just 14
-    'F' -> Just 15
-    'a' -> Just 10
-    'b' -> Just 11
-    'c' -> Just 12
-    'd' -> Just 13
-    'e' -> Just 14
-    'f' -> Just 15
-    _ -> fromDecimalDigit c
-
-isControl :: Char -> Bool
-isControl c = '\x00' <= c && c <= '\x1f'
-
-isDecimalDigit :: Char -> Bool
-isDecimalDigit c = '0' <= c && c <= '9'
-
-isHexadecimalDigit :: Char -> Bool
-isHexadecimalDigit c =
-  isDecimalDigit c || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
-
-isLiteral :: Char -> Bool
-isLiteral c = not (c == '"' || c == '\\' || isControl c)
-
-isNonZeroDigit :: Char -> Bool
-isNonZeroDigit c = '1' <= c && c <= '9'
-
-isWhitespace :: Char -> Bool
-isWhitespace c = c == '\t' || c == '\n' || c == '\r' || c == ' '
-
-negateIf :: Bool -> Integer -> Integer
-negateIf p n =
-  if p
-    then negate n
-    else n
-
-pSymbol :: String -> ReadP.ReadP ()
-pSymbol s = do
-  Functor.void (ReadP.string s)
-  pWhitespaces
-
-pWhitespaces :: ReadP.ReadP ()
-pWhitespaces = Functor.void (ReadP.munch isWhitespace)
-
-padLeft :: Integer -> a -> [a] -> [a]
-padLeft n x ys = reverse (padRight n x (reverse ys))
-
-padRight :: Integer -> a -> [a] -> [a]
-padRight n x ys =
-  if n <= 0
-    then ys
-    else case ys of
-           [] -> x : padRight (n - 1) x ys
-           y:zs -> y : padRight (n - 1) x zs
-
-runParser :: ReadP.ReadP a -> String -> Maybe a
-runParser p s =
-  Maybe.listToMaybe
-    (Maybe.mapMaybe
-       (\(x, t) ->
-          if null t
-            then Just x
-            else Nothing)
-       (ReadP.readP_to_S p s))
-
-sBetween :: ShowS -> ShowS -> (anything -> ShowS) -> anything -> ShowS
-sBetween left right render it = left . render it . right
-
-sSeparated :: ShowS -> (element -> ShowS) -> [element] -> ShowS
-sSeparated separator render elements =
-  case elements of
-    [] -> id
-    [element] -> render element
-    element:rest ->
-      render element . separator . sSeparated separator render rest
-
-sSeparatedBetween ::
-     ShowS -> ShowS -> ShowS -> (element -> ShowS) -> [element] -> ShowS
-sSeparatedBetween left right separator render elements =
-  sBetween left right (sSeparated separator render) elements
-
-toBase :: Integer -> (Integer -> Maybe Char) -> Integer -> String
-toBase b f n =
-  if n == 0
-    then [Maybe.fromJust (f n)]
-    else reverse (toBase' b f n)
-
-toBase' :: Integer -> (Integer -> Maybe Char) -> Integer -> String
-toBase' b f n =
-  case quotRem n b of
-    (0, 0) -> ""
-    (q, r) -> Maybe.fromJust (f r) : toBase' b f q
-
-toHexadecimal :: Integer -> String
-toHexadecimal n = toBase 16 toHexadecimalDigit n
-
-toHexadecimalDigit :: Integer -> Maybe Char
-toHexadecimalDigit n =
-  case n of
-    0 -> Just '0'
-    1 -> Just '1'
-    2 -> Just '2'
-    3 -> Just '3'
-    4 -> Just '4'
-    5 -> Just '5'
-    6 -> Just '6'
-    7 -> Just '7'
-    8 -> Just '8'
-    9 -> Just '9'
-    10 -> Just 'a'
-    11 -> Just 'b'
-    12 -> Just 'c'
-    13 -> Just 'd'
-    14 -> Just 'e'
-    15 -> Just 'f'
-    _ -> Nothing
-
--- | Tests taken from <https://github.com/nst/JSONTestSuite>.
---
--- >>> readJSON "[123.456e-789]" -- i_number_double_huge_neg_exp.json
--- Just (Array [Number 123456 (-792)])
--- >>> readJSON "[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]" -- i_number_huge_exp.json
--- Just (Array [Number (-4) 669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999005])
--- >>> readJSON "[-1e+9999]" -- i_number_neg_int_huge_exp.json
--- Just (Array [Number (-1) 9999])
--- >>> readJSON "[1.5e+9999]" -- i_number_pos_double_huge_exp.json
--- Just (Array [Number 15 9998])
--- >>> readJSON "[-123123e100000]" -- i_number_real_neg_overflow.json
--- Just (Array [Number (-123123) 100000])
--- >>> readJSON "[123123e100000]" -- i_number_real_pos_overflow.json
--- Just (Array [Number 123123 100000])
--- >>> readJSON "[123e-10000000]" -- i_number_real_underflow.json
--- Just (Array [Number 123 (-10000000)])
--- >>> readJSON "[-123123123123123123123123123123]" -- i_number_too_big_neg_int.json
--- Just (Array [Number (-123123123123123123123123123123) 0])
--- >>> readJSON "[100000000000000000000]" -- i_number_too_big_pos_int.json
--- Just (Array [Number 100000000000000000000 0])
--- >>> readJSON "[-237462374673276894279832749832423479823246327846]" -- i_number_very_big_negative_int.json
--- Just (Array [Number (-237462374673276894279832749832423479823246327846) 0])
--- >>> readJSON "{\"\\uDFAA\":0}" -- i_object_key_lone_2nd_surrogate.json
--- Just (Object [("\57258",Number 0 0)])
--- >>> readJSON "[\"\\uDADA\"]" -- i_string_1st_surrogate_but_2nd_missing.json
--- Just (Array [String "\56026"])
--- >>> readJSON "[\"\\uD888\\u1234\"]" -- i_string_1st_valid_surrogate_2nd_invalid.json
--- Just (Array [String "\55432\4660"])
--- >>> readJSON "[\"\\uD800\\n\"]" -- i_string_incomplete_surrogate_and_escape_valid.json
--- Just (Array [String "\55296\n"])
--- >>> readJSON "[\"\\uDd1ea\"]" -- i_string_incomplete_surrogate_pair.json
--- Just (Array [String "\56606a"])
--- >>> readJSON "[\"\\uD800\\uD800\\n\"]" -- i_string_incomplete_surrogates_escape_valid.json
--- Just (Array [String "\55296\55296\n"])
--- >>> readJSON "[\"\\ud800\"]" -- i_string_invalid_lonely_surrogate.json
--- Just (Array [String "\55296"])
--- >>> readJSON "[\"\\ud800abc\"]" -- i_string_invalid_surrogate.json
--- Just (Array [String "\55296abc"])
--- >>> readJSON "[\"\\uDd1e\\uD834\"]" -- i_string_inverted_surrogates_U+1D11E.json
--- Just (Array [String "\56606\55348"])
--- >>> readJSON "[\"\\uDFAA\"]" -- i_string_lone_second_surrogate.json
--- Just (Array [String "\57258"])
--- >>> readJSON "\65279{}" -- i_structure_UTF-8_BOM_empty_object.json
--- Nothing
--- >>> readJSON "[1 true]" -- n_array_1_true_without_comma.json
--- Nothing
--- >>> readJSON "[\"\": 1]" -- n_array_colon_instead_of_comma.json
--- Nothing
--- >>> readJSON "[\"\"]," -- n_array_comma_after_close.json
--- Nothing
--- >>> readJSON "[,1]" -- n_array_comma_and_number.json
--- Nothing
--- >>> readJSON "[1,,2]" -- n_array_double_comma.json
--- Nothing
--- >>> readJSON "[\"x\",,]" -- n_array_double_extra_comma.json
--- Nothing
--- >>> readJSON "[\"x\"]]" -- n_array_extra_close.json
--- Nothing
--- >>> readJSON "[\"\",]" -- n_array_extra_comma.json
--- Nothing
--- >>> readJSON "[\"x\"" -- n_array_incomplete.json
--- Nothing
--- >>> readJSON "[x" -- n_array_incomplete_invalid_value.json
--- Nothing
--- >>> readJSON "[3[4]]" -- n_array_inner_array_no_comma.json
--- Nothing
--- >>> readJSON "[1:2]" -- n_array_items_separated_by_semicolon.json
--- Nothing
--- >>> readJSON "[,]" -- n_array_just_comma.json
--- Nothing
--- >>> readJSON "[-]" -- n_array_just_minus.json
--- Nothing
--- >>> readJSON "[   , \"\"]" -- n_array_missing_value.json
--- Nothing
--- >>> readJSON "[\"a\",\n4\n,1," -- n_array_newlines_unclosed.json
--- Nothing
--- >>> readJSON "[1,]" -- n_array_number_and_comma.json
--- Nothing
--- >>> readJSON "[1,,]" -- n_array_number_and_several_commas.json
--- Nothing
--- >>> readJSON "[\"\va\"\\f]" -- n_array_spaces_vertical_tab_formfeed.json
--- Nothing
--- >>> readJSON "[*]" -- n_array_star_inside.json
--- Nothing
--- >>> readJSON "[\"\"" -- n_array_unclosed.json
--- Nothing
--- >>> readJSON "[1," -- n_array_unclosed_trailing_comma.json
--- Nothing
--- >>> readJSON "[1,\n1\n,1" -- n_array_unclosed_with_new_lines.json
--- Nothing
--- >>> readJSON "[{}" -- n_array_unclosed_with_object_inside.json
--- Nothing
--- >>> readJSON "[fals]" -- n_incomplete_false.json
--- Nothing
--- >>> readJSON "[nul]" -- n_incomplete_null.json
--- Nothing
--- >>> readJSON "[tru]" -- n_incomplete_true.json
--- Nothing
--- >>> readJSON "123\NUL" -- n_multidigit_number_then_00.json
--- Nothing
--- >>> readJSON "[++1234]" -- n_number_++.json
--- Nothing
--- >>> readJSON "[+1]" -- n_number_+1.json
--- Nothing
--- >>> readJSON "[+Inf]" -- n_number_+Inf.json
--- Nothing
--- >>> readJSON "[-01]" -- n_number_-01.json
--- Nothing
--- >>> readJSON "[-1.0.]" -- n_number_-1.0..json
--- Nothing
--- >>> readJSON "[-2.]" -- n_number_-2..json
--- Nothing
--- >>> readJSON "[-NaN]" -- n_number_-NaN.json
--- Nothing
--- >>> readJSON "[.-1]" -- n_number_.-1.json
--- Nothing
--- >>> readJSON "[.2e-3]" -- n_number_.2e-3.json
--- Nothing
--- >>> readJSON "[0.1.2]" -- n_number_0.1.2.json
--- Nothing
--- >>> readJSON "[0.3e+]" -- n_number_0.3e+.json
--- Nothing
--- >>> readJSON "[0.3e]" -- n_number_0.3e.json
--- Nothing
--- >>> readJSON "[0.e1]" -- n_number_0.e1.json
--- Nothing
--- >>> readJSON "[0E+]" -- n_number_0_capital_E+.json
--- Nothing
--- >>> readJSON "[0E]" -- n_number_0_capital_E.json
--- Nothing
--- >>> readJSON "[0e+]" -- n_number_0e+.json
--- Nothing
--- >>> readJSON "[0e]" -- n_number_0e.json
--- Nothing
--- >>> readJSON "[1.0e+]" -- n_number_1.0e+.json
--- Nothing
--- >>> readJSON "[1.0e-]" -- n_number_1.0e-.json
--- Nothing
--- >>> readJSON "[1.0e]" -- n_number_1.0e.json
--- Nothing
--- >>> readJSON "[1 000.0]" -- n_number_1_000.json
--- Nothing
--- >>> readJSON "[1eE2]" -- n_number_1eE2.json
--- Nothing
--- >>> readJSON "[2.e+3]" -- n_number_2.e+3.json
--- Nothing
--- >>> readJSON "[2.e-3]" -- n_number_2.e-3.json
--- Nothing
--- >>> readJSON "[2.e3]" -- n_number_2.e3.json
--- Nothing
--- >>> readJSON "[9.e+]" -- n_number_9.e+.json
--- Nothing
--- >>> readJSON "[Inf]" -- n_number_Inf.json
--- Nothing
--- >>> readJSON "[NaN]" -- n_number_NaN.json
--- Nothing
--- >>> readJSON "[\65297]" -- n_number_U+FF11_fullwidth_digit_one.json
--- Nothing
--- >>> readJSON "[1+2]" -- n_number_expression.json
--- Nothing
--- >>> readJSON "[0x1]" -- n_number_hex_1_digit.json
--- Nothing
--- >>> readJSON "[0x42]" -- n_number_hex_2_digits.json
--- Nothing
--- >>> readJSON "[Infinity]" -- n_number_infinity.json
--- Nothing
--- >>> readJSON "[0e+-1]" -- n_number_invalid+-.json
--- Nothing
--- >>> readJSON "[-123.123foo]" -- n_number_invalid-negative-real.json
--- Nothing
--- >>> readJSON "[-Infinity]" -- n_number_minus_infinity.json
--- Nothing
--- >>> readJSON "[-foo]" -- n_number_minus_sign_with_trailing_garbage.json
--- Nothing
--- >>> readJSON "[- 1]" -- n_number_minus_space_1.json
--- Nothing
--- >>> readJSON "[-012]" -- n_number_neg_int_starting_with_zero.json
--- Nothing
--- >>> readJSON "[-.123]" -- n_number_neg_real_without_int_part.json
--- Nothing
--- >>> readJSON "[-1x]" -- n_number_neg_with_garbage_at_end.json
--- Nothing
--- >>> readJSON "[1ea]" -- n_number_real_garbage_after_e.json
--- Nothing
--- >>> readJSON "[1.]" -- n_number_real_without_fractional_part.json
--- Nothing
--- >>> readJSON "[.123]" -- n_number_starting_with_dot.json
--- Nothing
--- >>> readJSON "[1.2a-3]" -- n_number_with_alpha.json
--- Nothing
--- >>> readJSON "[1.8011670033376514H-308]" -- n_number_with_alpha_char.json
--- Nothing
--- >>> readJSON "[012]" -- n_number_with_leading_zero.json
--- Nothing
--- >>> readJSON "[\"x\", truth]" -- n_object_bad_value.json
--- Nothing
--- >>> readJSON "{[: \"x\"}\n" -- n_object_bracket_key.json
--- Nothing
--- >>> readJSON "{\"x\", null}" -- n_object_comma_instead_of_colon.json
--- Nothing
--- >>> readJSON "{\"x\"::\"b\"}" -- n_object_double_colon.json
--- Nothing
--- >>> readJSON "{\127464\127469}" -- n_object_emoji.json
--- Nothing
--- >>> readJSON "{\"a\":\"a\" 123}" -- n_object_garbage_at_end.json
--- Nothing
--- >>> readJSON "{key: 'value'}" -- n_object_key_with_single_quotes.json
--- Nothing
--- >>> readJSON "{\"a\" b}" -- n_object_missing_colon.json
--- Nothing
--- >>> readJSON "{:\"b\"}" -- n_object_missing_key.json
--- Nothing
--- >>> readJSON "{\"a\" \"b\"}" -- n_object_missing_semicolon.json
--- Nothing
--- >>> readJSON "{\"a\":" -- n_object_missing_value.json
--- Nothing
--- >>> readJSON "{\"a\"" -- n_object_no-colon.json
--- Nothing
--- >>> readJSON "{1:1}" -- n_object_non_string_key.json
--- Nothing
--- >>> readJSON "{9999E9999:1}" -- n_object_non_string_key_but_huge_number_instead.json
--- Nothing
--- >>> readJSON "{null:null,null:null}" -- n_object_repeated_null_null.json
--- Nothing
--- >>> readJSON "{\"id\":0,,,,,}" -- n_object_several_trailing_commas.json
--- Nothing
--- >>> readJSON "{'a':0}" -- n_object_single_quote.json
--- Nothing
--- >>> readJSON "{\"id\":0,}" -- n_object_trailing_comma.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}/**/" -- n_object_trailing_comment.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}/**//" -- n_object_trailing_comment_open.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}//" -- n_object_trailing_comment_slash_open.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}/" -- n_object_trailing_comment_slash_open_incomplete.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\",,\"c\":\"d\"}" -- n_object_two_commas_in_a_row.json
--- Nothing
--- >>> readJSON "{a: \"b\"}" -- n_object_unquoted_key.json
--- Nothing
--- >>> readJSON "{\"a\":\"a" -- n_object_unterminated-value.json
--- Nothing
--- >>> readJSON "{ \"foo\" : \"bar\", \"a\" }" -- n_object_with_single_string.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}#" -- n_object_with_trailing_garbage.json
--- Nothing
--- >>> readJSON " " -- n_single_space.json
--- Nothing
--- >>> readJSON "[\"\\uD800\\\"]" -- n_string_1_surrogate_then_escape.json
--- Nothing
--- >>> readJSON "[\"\\uD800\\u\"]" -- n_string_1_surrogate_then_escape_u.json
--- Nothing
--- >>> readJSON "[\"\\uD800\\u1\"]" -- n_string_1_surrogate_then_escape_u1.json
--- Nothing
--- >>> readJSON "[\"\\uD800\\u1x\"]" -- n_string_1_surrogate_then_escape_u1x.json
--- Nothing
--- >>> readJSON "[\233]" -- n_string_accentuated_char_no_quotes.json
--- Nothing
--- >>> readJSON "[\"\\\NUL\"]" -- n_string_backslash_00.json
--- Nothing
--- >>> readJSON "[\"\\x00\"]" -- n_string_escape_x.json
--- Nothing
--- >>> readJSON "[\"\\\\\\\"]" -- n_string_escaped_backslash_bad.json
--- Nothing
--- >>> readJSON "[\"\\\t\"]" -- n_string_escaped_ctrl_char_tab.json
--- Nothing
--- >>> readJSON "[\"\\\127744\"]" -- n_string_escaped_emoji.json
--- Nothing
--- >>> readJSON "[\"\\\"]" -- n_string_incomplete_escape.json
--- Nothing
--- >>> readJSON "[\"\\u00A\"]" -- n_string_incomplete_escaped_character.json
--- Nothing
--- >>> readJSON "[\"\\uD834\\uDd\"]" -- n_string_incomplete_surrogate.json
--- Nothing
--- >>> readJSON "[\"\\uD800\\uD800\\x\"]" -- n_string_incomplete_surrogate_escape_invalid.json
--- Nothing
--- >>> readJSON "[\"\\a\"]" -- n_string_invalid_backslash_esc.json
--- Nothing
--- >>> readJSON "[\"\\uqqqq\"]" -- n_string_invalid_unicode_escape.json
--- Nothing
--- >>> readJSON "[\\u0020\"asd\"]" -- n_string_leading_uescaped_thinspace.json
--- Nothing
--- >>> readJSON "[\\n]" -- n_string_no_quotes_with_bad_escape.json
--- Nothing
--- >>> readJSON "\"" -- n_string_single_doublequote.json
--- Nothing
--- >>> readJSON "['single quote']" -- n_string_single_quote.json
--- Nothing
--- >>> readJSON "abc" -- n_string_single_string_no_double_quotes.json
--- Nothing
--- >>> readJSON "[\"\\" -- n_string_start_escape_unclosed.json
--- Nothing
--- >>> readJSON "[\"a\NULa\"]" -- n_string_unescaped_crtl_char.json
--- Nothing
--- >>> readJSON "[\"new\nline\"]" -- n_string_unescaped_newline.json
--- Nothing
--- >>> readJSON "[\"\t\"]" -- n_string_unescaped_tab.json
--- Nothing
--- >>> readJSON "\"\\UA66D\"" -- n_string_unicode_CapitalU.json
--- Nothing
--- >>> readJSON "\"\"x" -- n_string_with_trailing_garbage.json
--- Nothing
--- >>> readJSON "[\8288]" -- n_structure_U+2060_word_joined.json
--- Nothing
--- >>> readJSON "\65279" -- n_structure_UTF8_BOM_no_data.json
--- Nothing
--- >>> readJSON "<.>" -- n_structure_angle_bracket_..json
--- Nothing
--- >>> readJSON "[<null>]" -- n_structure_angle_bracket_null.json
--- Nothing
--- >>> readJSON "[1]x" -- n_structure_array_trailing_garbage.json
--- Nothing
--- >>> readJSON "[1]]" -- n_structure_array_with_extra_array_close.json
--- Nothing
--- >>> readJSON "[\"asd]" -- n_structure_array_with_unclosed_string.json
--- Nothing
--- >>> readJSON "a\229" -- n_structure_ascii-unicode-identifier.json
--- Nothing
--- >>> readJSON "[True]" -- n_structure_capitalized_True.json
--- Nothing
--- >>> readJSON "1]" -- n_structure_close_unopened_array.json
--- Nothing
--- >>> readJSON "{\"x\": true," -- n_structure_comma_instead_of_closing_brace.json
--- Nothing
--- >>> readJSON "[][]" -- n_structure_double_array.json
--- Nothing
--- >>> readJSON "]" -- n_structure_end_array.json
--- Nothing
--- >>> readJSON "[" -- n_structure_lone-open-bracket.json
--- Nothing
--- >>> readJSON "" -- n_structure_no_data.json
--- Nothing
--- >>> readJSON "[\NUL]" -- n_structure_null-byte-outside-string.json
--- Nothing
--- >>> readJSON "2@" -- n_structure_number_with_trailing_garbage.json
--- Nothing
--- >>> readJSON "{}}" -- n_structure_object_followed_by_closing_object.json
--- Nothing
--- >>> readJSON "{\"\":" -- n_structure_object_unclosed_no_value.json
--- Nothing
--- >>> readJSON "{\"a\":/*comment*/\"b\"}" -- n_structure_object_with_comment.json
--- Nothing
--- >>> readJSON "{\"a\": true} \"x\"" -- n_structure_object_with_trailing_garbage.json
--- Nothing
--- >>> readJSON "['" -- n_structure_open_array_apostrophe.json
--- Nothing
--- >>> readJSON "[," -- n_structure_open_array_comma.json
--- Nothing
--- >>> readJSON "[{" -- n_structure_open_array_open_object.json
--- Nothing
--- >>> readJSON "[\"a" -- n_structure_open_array_open_string.json
--- Nothing
--- >>> readJSON "[\"a\"" -- n_structure_open_array_string.json
--- Nothing
--- >>> readJSON "{" -- n_structure_open_object.json
--- Nothing
--- >>> readJSON "{]" -- n_structure_open_object_close_array.json
--- Nothing
--- >>> readJSON "{," -- n_structure_open_object_comma.json
--- Nothing
--- >>> readJSON "{[" -- n_structure_open_object_open_array.json
--- Nothing
--- >>> readJSON "{\"a" -- n_structure_open_object_open_string.json
--- Nothing
--- >>> readJSON "{'a'" -- n_structure_open_object_string_with_apostrophes.json
--- Nothing
--- >>> readJSON "[\"\\{[\"\\{[\"\\{[\"\\{" -- n_structure_open_open.json
--- Nothing
--- >>> readJSON "*" -- n_structure_single_star.json
--- Nothing
--- >>> readJSON "{\"a\":\"b\"}#{}" -- n_structure_trailing_#.json
--- Nothing
--- >>> readJSON "[\\u000A\"\"]" -- n_structure_uescaped_LF_before_string.json
--- Nothing
--- >>> readJSON "[1" -- n_structure_unclosed_array.json
--- Nothing
--- >>> readJSON "[ false, nul" -- n_structure_unclosed_array_partial_null.json
--- Nothing
--- >>> readJSON "[ true, fals" -- n_structure_unclosed_array_unfinished_false.json
--- Nothing
--- >>> readJSON "[ false, tru" -- n_structure_unclosed_array_unfinished_true.json
--- Nothing
--- >>> readJSON "{\"asd\":\"asd\"" -- n_structure_unclosed_object.json
--- Nothing
--- >>> readJSON "\229" -- n_structure_unicode-identifier.json
--- Nothing
--- >>> readJSON "[\8288]" -- n_structure_whitespace_U+2060_word_joiner.json
--- Nothing
--- >>> readJSON "[\f]" -- n_structure_whitespace_formfeed.json
--- Nothing
--- >>> readJSON "[[]   ]" -- y_array_arraysWithSpaces.json
--- Just (Array [Array []])
--- >>> readJSON "[\"\"]" -- y_array_empty-string.json
--- Just (Array [String ""])
--- >>> readJSON "[]" -- y_array_empty.json
--- Just (Array [])
--- >>> readJSON "[\"a\"]" -- y_array_ending_with_newline.json
--- Just (Array [String "a"])
--- >>> readJSON "[false]" -- y_array_false.json
--- Just (Array [Boolean False])
--- >>> readJSON "[null, 1, \"1\", {}]" -- y_array_heterogeneous.json
--- Just (Array [Null,Number 1 0,String "1",Object []])
--- >>> readJSON "[null]" -- y_array_null.json
--- Just (Array [Null])
--- >>> readJSON "[1\n]" -- y_array_with_1_and_newline.json
--- Just (Array [Number 1 0])
--- >>> readJSON " [1]" -- y_array_with_leading_space.json
--- Just (Array [Number 1 0])
--- >>> readJSON "[1,null,null,null,2]" -- y_array_with_several_null.json
--- Just (Array [Number 1 0,Null,Null,Null,Number 2 0])
--- >>> readJSON "[2] " -- y_array_with_trailing_space.json
--- Just (Array [Number 2 0])
--- >>> readJSON "[123e65]" -- y_number.json
--- Just (Array [Number 123 65])
--- >>> readJSON "[0e+1]" -- y_number_0e+1.json
--- Just (Array [Number 0 1])
--- >>> readJSON "[0e1]" -- y_number_0e1.json
--- Just (Array [Number 0 1])
--- >>> readJSON "[ 4]" -- y_number_after_space.json
--- Just (Array [Number 4 0])
--- >>> readJSON "[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]\n" -- y_number_double_close_to_zero.json
--- Just (Array [Number (-1) (-78)])
--- >>> readJSON "[20e1]" -- y_number_int_with_exp.json
--- Just (Array [Number 20 1])
--- >>> readJSON "[-0]" -- y_number_minus_zero.json
--- Just (Array [Number 0 0])
--- >>> readJSON "[-123]" -- y_number_negative_int.json
--- Just (Array [Number (-123) 0])
--- >>> readJSON "[-1]" -- y_number_negative_one.json
--- Just (Array [Number (-1) 0])
--- >>> readJSON "[-0]" -- y_number_negative_zero.json
--- Just (Array [Number 0 0])
--- >>> readJSON "[1E22]" -- y_number_real_capital_e.json
--- Just (Array [Number 1 22])
--- >>> readJSON "[1E-2]" -- y_number_real_capital_e_neg_exp.json
--- Just (Array [Number 1 (-2)])
--- >>> readJSON "[1E+2]" -- y_number_real_capital_e_pos_exp.json
--- Just (Array [Number 1 2])
--- >>> readJSON "[123e45]" -- y_number_real_exponent.json
--- Just (Array [Number 123 45])
--- >>> readJSON "[123.456e78]" -- y_number_real_fraction_exponent.json
--- Just (Array [Number 123456 75])
--- >>> readJSON "[1e-2]" -- y_number_real_neg_exp.json
--- Just (Array [Number 1 (-2)])
--- >>> readJSON "[1e+2]" -- y_number_real_pos_exponent.json
--- Just (Array [Number 1 2])
--- >>> readJSON "[123]" -- y_number_simple_int.json
--- Just (Array [Number 123 0])
--- >>> readJSON "[123.456789]" -- y_number_simple_real.json
--- Just (Array [Number 123456789 (-6)])
--- >>> readJSON "{\"asd\":\"sdf\", \"dfg\":\"fgh\"}" -- y_object.json
--- Just (Object [("asd",String "sdf"),("dfg",String "fgh")])
--- >>> readJSON "{\"asd\":\"sdf\"}" -- y_object_basic.json
--- Just (Object [("asd",String "sdf")])
--- >>> readJSON "{\"a\":\"b\",\"a\":\"c\"}" -- y_object_duplicated_key.json
--- Just (Object [("a",String "b"),("a",String "c")])
--- >>> readJSON "{\"a\":\"b\",\"a\":\"b\"}" -- y_object_duplicated_key_and_value.json
--- Just (Object [("a",String "b"),("a",String "b")])
--- >>> readJSON "{}" -- y_object_empty.json
--- Just (Object [])
--- >>> readJSON "{\"\":0}" -- y_object_empty_key.json
--- Just (Object [("",Number 0 0)])
--- >>> readJSON "{\"foo\\u0000bar\": 42}" -- y_object_escaped_null_in_key.json
--- Just (Object [("foo\NULbar",Number 42 0)])
--- >>> readJSON "{ \"min\": -1.0e+28, \"max\": 1.0e+28 }" -- y_object_extreme_numbers.json
--- Just (Object [("min",Number (-10) 27),("max",Number 10 27)])
--- >>> readJSON "{\"x\":[{\"id\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}], \"id\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}" -- y_object_long_strings.json
--- Just (Object [("x",Array [Object [("id",String "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")]]),("id",String "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")])
--- >>> readJSON "{\"a\":[]}" -- y_object_simple.json
--- Just (Object [("a",Array [])])
--- >>> readJSON "{\"title\":\"\\u041f\\u043e\\u043b\\u0442\\u043e\\u0440\\u0430 \\u0417\\u0435\\u043c\\u043b\\u0435\\u043a\\u043e\\u043f\\u0430\" }" -- y_object_string_unicode.json
--- Just (Object [("title",String "\1055\1086\1083\1090\1086\1088\1072 \1047\1077\1084\1083\1077\1082\1086\1087\1072")])
--- >>> readJSON "{\n\"a\": \"b\"\n}" -- y_object_with_newlines.json
--- Just (Object [("a",String "b")])
--- >>> readJSON "[\"\\u0060\\u012a\\u12AB\"]" -- y_string_1_2_3_bytes_UTF-8_sequences.json
--- Just (Array [String "`\298\4779"])
--- >>> readJSON "[\"\\uD801\\udc37\"]" -- y_string_accepted_surrogate_pair.json
--- Just (Array [String "\55297\56375"])
--- >>> readJSON "[\"\\ud83d\\ude39\\ud83d\\udc8d\"]" -- y_string_accepted_surrogate_pairs.json
--- Just (Array [String "\55357\56889\55357\56461"])
--- >>> readJSON "[\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"]" -- y_string_allowed_escapes.json
--- Just (Array [String "\"\\/\b\f\n\r\t"])
--- >>> readJSON "[\"\\\\u0000\"]" -- y_string_backslash_and_u_escaped_zero.json
--- Just (Array [String "\\u0000"])
--- >>> readJSON "[\"\\\"\"]" -- y_string_backslash_doublequotes.json
--- Just (Array [String "\""])
--- >>> readJSON "[\"a/*b*/c/*d//e\"]" -- y_string_comments.json
--- Just (Array [String "a/*b*/c/*d//e"])
--- >>> readJSON "[\"\\\\a\"]" -- y_string_double_escape_a.json
--- Just (Array [String "\\a"])
--- >>> readJSON "[\"\\\\n\"]" -- y_string_double_escape_n.json
--- Just (Array [String "\\n"])
--- >>> readJSON "[\"\\u0012\"]" -- y_string_escaped_control_character.json
--- Just (Array [String "\DC2"])
--- >>> readJSON "[\"\\uFFFF\"]" -- y_string_escaped_noncharacter.json
--- Just (Array [String "\65535"])
--- >>> readJSON "[\"asd\"]" -- y_string_in_array.json
--- Just (Array [String "asd"])
--- >>> readJSON "[ \"asd\"]" -- y_string_in_array_with_leading_space.json
--- Just (Array [String "asd"])
--- >>> readJSON "[\"\\uDBFF\\uDFFF\"]" -- y_string_last_surrogates_1_and_2.json
--- Just (Array [String "\56319\57343"])
--- >>> readJSON "[\"new\\u00A0line\"]" -- y_string_nbsp_uescaped.json
--- Just (Array [String "new\160line"])
--- >>> readJSON "[\"\1114111\"]" -- y_string_nonCharacterInUTF-8_U+10FFFF.json
--- Just (Array [String "\1114111"])
--- >>> readJSON "[\"\114687\"]" -- y_string_nonCharacterInUTF-8_U+1FFFF.json
--- Just (Array [String "\114687"])
--- >>> readJSON "[\"\65535\"]" -- y_string_nonCharacterInUTF-8_U+FFFF.json
--- Just (Array [String "\65535"])
--- >>> readJSON "[\"\\u0000\"]" -- y_string_null_escape.json
--- Just (Array [String "\NUL"])
--- >>> readJSON "[\"\\u002c\"]" -- y_string_one-byte-utf-8.json
--- Just (Array [String ","])
--- >>> readJSON "[\"\960\"]" -- y_string_pi.json
--- Just (Array [String "\960"])
--- >>> readJSON "[\"asd \"]" -- y_string_simple_ascii.json
--- Just (Array [String "asd "])
--- >>> readJSON "\" \"" -- y_string_space.json
--- Just (String " ")
--- >>> readJSON "[\"\\uD834\\uDd1e\"]" -- y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json
--- Just (Array [String "\55348\56606"])
--- >>> readJSON "[\"\\u0821\"]" -- y_string_three-byte-utf-8.json
--- Just (Array [String "\2081"])
--- >>> readJSON "[\"\\u0123\"]" -- y_string_two-byte-utf-8.json
--- Just (Array [String "\291"])
--- >>> readJSON "[\"\8232\"]" -- y_string_u+2028_line_sep.json
--- Just (Array [String "\8232"])
--- >>> readJSON "[\"\8233\"]" -- y_string_u+2029_par_sep.json
--- Just (Array [String "\8233"])
--- >>> readJSON "[\"\\u0061\\u30af\\u30EA\\u30b9\"]" -- y_string_uEscape.json
--- Just (Array [String "a\12463\12522\12473"])
--- >>> readJSON "[\"new\\u000Aline\"]" -- y_string_uescaped_newline.json
--- Just (Array [String "new\nline"])
--- >>> readJSON "[\"\DEL\"]" -- y_string_unescaped_char_delete.json
--- Just (Array [String "\DEL"])
--- >>> readJSON "[\"\\uA66D\"]" -- y_string_unicode.json
--- Just (Array [String "\42605"])
--- >>> readJSON "[\"\\u005C\"]" -- y_string_unicodeEscapedBackslash.json
--- Just (Array [String "\\"])
--- >>> readJSON "[\"\9026\12852\9026\"]" -- y_string_unicode_2.json
--- Just (Array [String "\9026\12852\9026"])
--- >>> readJSON "[\"\\uDBFF\\uDFFE\"]" -- y_string_unicode_U+10FFFE_nonchar.json
--- Just (Array [String "\56319\57342"])
--- >>> readJSON "[\"\\uD83F\\uDFFE\"]" -- y_string_unicode_U+1FFFE_nonchar.json
--- Just (Array [String "\55359\57342"])
--- >>> readJSON "[\"\\u200B\"]" -- y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json
--- Just (Array [String "\8203"])
--- >>> readJSON "[\"\\u2064\"]" -- y_string_unicode_U+2064_invisible_plus.json
--- Just (Array [String "\8292"])
--- >>> readJSON "[\"\\uFDD0\"]" -- y_string_unicode_U+FDD0_nonchar.json
--- Just (Array [String "\64976"])
--- >>> readJSON "[\"\\uFFFE\"]" -- y_string_unicode_U+FFFE_nonchar.json
--- Just (Array [String "\65534"])
--- >>> readJSON "[\"\\u0022\"]" -- y_string_unicode_escaped_double_quote.json
--- Just (Array [String "\""])
--- >>> readJSON "[\"\8364\119070\"]" -- y_string_utf8.json
--- Just (Array [String "\8364\119070"])
--- >>> readJSON "[\"a\DELa\"]" -- y_string_with_del_character.json
--- Just (Array [String "a\DELa"])
--- >>> readJSON "false" -- y_structure_lonely_false.json
--- Just (Boolean False)
--- >>> readJSON "42" -- y_structure_lonely_int.json
--- Just (Number 42 0)
--- >>> readJSON "-0.1" -- y_structure_lonely_negative_real.json
--- Just (Number (-1) (-1))
--- >>> readJSON "null" -- y_structure_lonely_null.json
--- Just Null
--- >>> readJSON "\"asd\"" -- y_structure_lonely_string.json
--- Just (String "asd")
--- >>> readJSON "true" -- y_structure_lonely_true.json
--- Just (Boolean True)
--- >>> readJSON "\"\"" -- y_structure_string_empty.json
--- Just (String "")
--- >>> readJSON "[\"a\"]\n" -- y_structure_trailing_newline.json
--- Just (Array [String "a"])
--- >>> readJSON "[true]" -- y_structure_true_in_array.json
--- Just (Array [Boolean True])
--- >>> readJSON " [] " -- y_structure_whitespace_array.json
--- Just (Array [])
---
--- >>> readJSON "[1.0]" -- number_1.0.json
--- Just (Array [Number 10 (-1)])
--- >>> readJSON "[1.000000000000000005]" -- number_1.000000000000000005.json
--- Just (Array [Number 1000000000000000005 (-18)])
--- >>> readJSON "[1000000000000000]\n" -- number_1000000000000000.json
--- Just (Array [Number 1000000000000000 0])
--- >>> readJSON "[10000000000000000999]" -- number_10000000000000000999.json
--- Just (Array [Number 10000000000000000999 0])
--- >>> readJSON "[1E-999]" -- number_1e-999.json
--- Just (Array [Number 1 (-999)])
--- >>> readJSON "[1E6]" -- number_1e6.json
--- Just (Array [Number 1 6])
--- >>> readJSON "{\"\233\":\"NFC\",\"e\769\":\"NFD\"}" -- object_key_nfc_nfd.json
--- Just (Object [("\233",String "NFC"),("e\769",String "NFD")])
--- >>> readJSON "{\"e\769\":\"NFD\",\"\233\":\"NFC\"}" -- object_key_nfd_nfc.json
--- Just (Object [("e\769",String "NFD"),("\233",String "NFC")])
--- >>> readJSON "{\"a\":1,\"a\":2}" -- object_same_key_different_values.json
--- Just (Object [("a",Number 1 0),("a",Number 2 0)])
--- >>> readJSON "{\"a\":1,\"a\":1}" -- object_same_key_same_value.json
--- Just (Object [("a",Number 1 0),("a",Number 1 0)])
--- >>> readJSON "{\"a\":0, \"a\":-0}\n" -- object_same_key_unclear_values.json
--- Just (Object [("a",Number 0 0),("a",Number 0 0)])
--- >>> readJSON "[\"\\uD800\"]" -- string_1_escaped_invalid_codepoint.json
--- Just (Array [String "\55296"])
--- >>> readJSON "[\"\\uD800\\uD800\"]" -- string_2_escaped_invalid_codepoints.json
--- Just (Array [String "\55296\55296"])
--- >>> readJSON "[\"\\uD800\\uD800\\uD800\"]" -- string_3_escaped_invalid_codepoints.json
--- Just (Array [String "\55296\55296\55296"])
--- >>> readJSON "[\"A\\u0000B\"]" -- string_with_escaped_NULL.json
--- Just (Array [String "A\NULB"])
diff --git a/package.yaml b/package.yaml
deleted file mode 100644
--- a/package.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-name: derulo
-version: 1.0.8
-
-category: JSON
-description: Derulo parses and renders JSON simply.
-extra-source-files:
-  - CHANGELOG.markdown
-  - package.yaml
-  - README.markdown
-  - stack.yaml
-github: tfausak/derulo
-license-file: LICENSE.markdown
-license: MIT
-maintainer: Taylor Fausak
-synopsis: Parse and render JSON simply.
-
-dependencies:
-  base: '>= 4.9.0 && < 4.15'
-ghc-options:
-  - -Weverything
-  - -Wno-implicit-prelude
-  - -Wno-safe
-  - -Wno-unsafe
-
-when:
-  - condition: impl(ghc >= 8.8.1)
-    ghc-options: -Wno-missing-deriving-strategies
-
-library:
-  source-dirs: library
-
-executable:
-  dependencies:
-    derulo: -any
-  ghc-options:
-    - -rtsopts
-    - -threaded
-  main: Main.hs
-  source-dirs: executables
-
-tests:
-  test:
-    dependencies:
-      doctest: '>= 0.11.0 && < 0.17'
-    ghc-options:
-      - -rtsopts
-      - -threaded
-    main: Main.hs
-    source-dirs: tests
diff --git a/src/exe/Main.hs b/src/exe/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/exe/Main.hs
@@ -0,0 +1,5 @@
+import qualified Data.Maybe as Maybe
+import qualified Derulo
+
+main :: IO ()
+main = interact (Derulo.showJSON . Maybe.fromJust . Derulo.readJSON)
diff --git a/src/lib/Derulo.hs b/src/lib/Derulo.hs
new file mode 100644
--- /dev/null
+++ b/src/lib/Derulo.hs
@@ -0,0 +1,408 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+-- | Derulo parses and renders JSON simply. It aims to provide an RFC 7159
+-- compliant parser and renderer without incurring any dependencies. It is
+-- intended to be used either for learning or in situations where dependencies
+-- are unwanted. In normal usage, prefer a faster, more robust library like
+-- [Aeson](https://hackage.haskell.org/package/aeson).
+--
+-- Derulo does not export any identifiers that conflict with the prelude and
+-- can be imported unqualified.
+--
+-- >>> import Derulo
+--
+-- Use 'readJSON' to parse a 'String' into a 'JSON' value.
+--
+-- >>> readJSON " null "
+-- Just Null
+--
+-- Use 'showJSON' to render a 'JSON' value as a 'String'.
+--
+-- >>> showJSON Null
+-- "null"
+module Derulo
+  ( JSON(..)
+  , readJSON
+  , showJSON
+  ) where
+
+import qualified Control.Monad as Monad
+import qualified Data.Data as Data
+import qualified Data.Functor as Functor
+import qualified Data.List as List
+import qualified Data.Maybe as Maybe
+import qualified GHC.Generics as Generics
+import qualified Text.ParserCombinators.ReadP as ReadP
+
+-- * Types
+-- | A JSON value as described by RFC 7159.
+data JSON
+  = Null
+  | Boolean Bool
+  | Number Integer
+           Integer
+  | String String
+  | Array [JSON]
+  | Object [(String, JSON)]
+  deriving (Data.Data, Eq, Generics.Generic, Ord, Read, Show)
+
+-- * Parsing
+-- | Parses a string as JSON.
+readJSON :: String -> Maybe JSON
+readJSON string = runParser pJSON string
+
+pJSON :: ReadP.ReadP JSON
+pJSON = do
+  pWhitespaces
+  value <- pValue
+  ReadP.eof
+  pure value
+
+pValue :: ReadP.ReadP JSON
+pValue = ReadP.choice [pNull, pBoolean, pNumber, pString, pArray, pObject]
+
+pNull :: ReadP.ReadP JSON
+pNull = do
+  pSymbol "null"
+  pure Null
+
+pBoolean :: ReadP.ReadP JSON
+pBoolean = pTrue ReadP.+++ pFalse
+
+pTrue :: ReadP.ReadP JSON
+pTrue = do
+  pSymbol "true"
+  pure (Boolean True)
+
+pFalse :: ReadP.ReadP JSON
+pFalse = do
+  pSymbol "false"
+  pure (Boolean False)
+
+pNumber :: ReadP.ReadP JSON
+pNumber = do
+  integer <- pInteger
+  (fraction, precision) <- ReadP.option (0, 0) pFraction
+  power <- ReadP.option 0 pPower
+  pWhitespaces
+  let mantissa = integer * 10 ^ precision + negateIf (integer <= 0) fraction
+  let magnitude = power - precision
+  pure (Number mantissa magnitude)
+
+pInteger :: ReadP.ReadP Integer
+pInteger = pZero ReadP.+++ pNonZero
+
+pZero :: ReadP.ReadP Integer
+pZero = do
+  ReadP.optional (ReadP.char '-')
+  Functor.void (ReadP.char '0')
+  pure 0
+
+pNonZero :: ReadP.ReadP Integer
+pNonZero = do
+  sign <- ReadP.option '+' (ReadP.char '-')
+  first <- ReadP.satisfy isNonZeroDigit
+  rest <- ReadP.munch isDecimalDigit
+  case fromDecimal (first : rest) of
+    Nothing -> ReadP.pfail
+    Just nonZero -> pure (negateIf (sign == '-') nonZero)
+
+pFraction :: ReadP.ReadP (Integer, Integer)
+pFraction = do
+  Functor.void (ReadP.char '.')
+  digits <- ReadP.munch1 isDecimalDigit
+  case fromDecimal digits of
+    Nothing -> ReadP.pfail
+    Just fraction -> pure (fraction, List.genericLength digits)
+
+pPower :: ReadP.ReadP Integer
+pPower = do
+  Functor.void (ReadP.char 'E' ReadP.+++ ReadP.char 'e')
+  sign <- ReadP.option '+' (ReadP.char '+' ReadP.+++ ReadP.char '-')
+  digits <- ReadP.munch1 isDecimalDigit
+  case fromDecimal digits of
+    Nothing -> ReadP.pfail
+    Just magnitude -> pure (negateIf (sign == '-') magnitude)
+
+pString :: ReadP.ReadP JSON
+pString = do
+  string <-
+    ReadP.between
+      (ReadP.char '"')
+      (ReadP.char '"')
+      (do characters <- ReadP.many pCharacter
+          pure (String characters))
+  pWhitespaces
+  pure string
+
+pCharacter :: ReadP.ReadP Char
+pCharacter = pLiteral ReadP.+++ pEscape
+
+pLiteral :: ReadP.ReadP Char
+pLiteral = ReadP.satisfy isLiteral
+
+pEscape :: ReadP.ReadP Char
+pEscape = do
+  Functor.void (ReadP.char '\\')
+  escape <- ReadP.get
+  case escape of
+    '"' -> pure '"'
+    '/' -> pure '/'
+    '\\' -> pure '\\'
+    'b' -> pure '\b'
+    'f' -> pure '\f'
+    'n' -> pure '\n'
+    'r' -> pure '\r'
+    't' -> pure '\t'
+    'u' -> do
+      digits <- ReadP.count 4 (ReadP.satisfy isHexadecimalDigit)
+      case fromHexadecimal digits of
+        Nothing -> ReadP.pfail
+        Just point -> pure (toEnum (fromIntegral point))
+    _ -> ReadP.pfail
+
+pArray :: ReadP.ReadP JSON
+pArray =
+  ReadP.between
+    (pSymbol "[")
+    (pSymbol "]")
+    (do values <- ReadP.sepBy pValue (pSymbol ",")
+        pure (Array values))
+
+pObject :: ReadP.ReadP JSON
+pObject =
+  ReadP.between
+    (pSymbol "{")
+    (pSymbol "}")
+    (do pairs <- ReadP.sepBy pPair (pSymbol ",")
+        pure (Object pairs))
+
+pPair :: ReadP.ReadP (String, JSON)
+pPair = do
+  String key <- pString
+  pSymbol ":"
+  value <- pValue
+  pure (key, value)
+
+-- * Rendering
+-- | Renders JSON as a string.
+showJSON :: JSON -> String
+showJSON json = sJSON json ""
+
+sJSON :: JSON -> ShowS
+sJSON json =
+  case json of
+    Null -> sNull
+    Boolean boolean -> sBoolean boolean
+    Number mantissa magnitude -> sNumber mantissa magnitude
+    String string -> sString string
+    Array array -> sArray array
+    Object object -> sObject object
+
+sNull :: ShowS
+sNull = showString "null"
+
+sBoolean :: Bool -> ShowS
+sBoolean boolean =
+  if boolean
+    then sTrue
+    else sFalse
+
+sTrue :: ShowS
+sTrue = showString "true"
+
+sFalse :: ShowS
+sFalse = showString "false"
+
+sNumber :: Integer -> Integer -> ShowS
+sNumber mantissa magnitude = shows mantissa . showChar 'e' . shows magnitude
+
+sString :: String -> ShowS
+sString string =
+  sSeparatedBetween (showChar '"') (showChar '"') id sCharacter string
+
+sCharacter :: Char -> ShowS
+sCharacter character =
+  case character of
+    '"' -> showString "\\\""
+    '\\' -> showString "\\\\"
+    '\b' -> showString "\\b"
+    '\f' -> showString "\\f"
+    '\n' -> showString "\\n"
+    '\r' -> showString "\\r"
+    '\t' -> showString "\\t"
+    _ ->
+      if isControl character
+        then showString "\\u" .
+             showString
+               (padLeft
+                  4
+                  '0'
+                  (toHexadecimal (fromIntegral (fromEnum character))))
+        else showChar character
+
+sArray :: [JSON] -> ShowS
+sArray array =
+  sSeparatedBetween (showChar '[') (showChar ']') (showChar ',') sJSON array
+
+sObject :: [(String, JSON)] -> ShowS
+sObject object =
+  sSeparatedBetween (showChar '{') (showChar '}') (showChar ',') sPair object
+
+sPair :: (String, JSON) -> ShowS
+sPair (key, value) = sString key . showChar ':' . sJSON value
+
+-- * Helpers
+fromBase :: Integer -> (Char -> Maybe Integer) -> String -> Maybe Integer
+fromBase b f s =
+  Monad.foldM
+    (\n c -> do
+       d <- f c
+       pure (b * n + d))
+    0
+    s
+
+fromDecimal :: String -> Maybe Integer
+fromDecimal s = fromBase 10 fromDecimalDigit s
+
+fromDecimalDigit :: Char -> Maybe Integer
+fromDecimalDigit c =
+  case c of
+    '0' -> Just 0
+    '1' -> Just 1
+    '2' -> Just 2
+    '3' -> Just 3
+    '4' -> Just 4
+    '5' -> Just 5
+    '6' -> Just 6
+    '7' -> Just 7
+    '8' -> Just 8
+    '9' -> Just 9
+    _ -> Nothing
+
+fromHexadecimal :: String -> Maybe Integer
+fromHexadecimal s = fromBase 16 fromHexadecimalDigit s
+
+fromHexadecimalDigit :: Char -> Maybe Integer
+fromHexadecimalDigit c =
+  case c of
+    'A' -> Just 10
+    'B' -> Just 11
+    'C' -> Just 12
+    'D' -> Just 13
+    'E' -> Just 14
+    'F' -> Just 15
+    'a' -> Just 10
+    'b' -> Just 11
+    'c' -> Just 12
+    'd' -> Just 13
+    'e' -> Just 14
+    'f' -> Just 15
+    _ -> fromDecimalDigit c
+
+isControl :: Char -> Bool
+isControl c = '\x00' <= c && c <= '\x1f'
+
+isDecimalDigit :: Char -> Bool
+isDecimalDigit c = '0' <= c && c <= '9'
+
+isHexadecimalDigit :: Char -> Bool
+isHexadecimalDigit c =
+  isDecimalDigit c || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
+
+isLiteral :: Char -> Bool
+isLiteral c = not (c == '"' || c == '\\' || isControl c)
+
+isNonZeroDigit :: Char -> Bool
+isNonZeroDigit c = '1' <= c && c <= '9'
+
+isWhitespace :: Char -> Bool
+isWhitespace c = c == '\t' || c == '\n' || c == '\r' || c == ' '
+
+negateIf :: Bool -> Integer -> Integer
+negateIf p n =
+  if p
+    then negate n
+    else n
+
+pSymbol :: String -> ReadP.ReadP ()
+pSymbol s = do
+  Functor.void (ReadP.string s)
+  pWhitespaces
+
+pWhitespaces :: ReadP.ReadP ()
+pWhitespaces = Functor.void (ReadP.munch isWhitespace)
+
+padLeft :: Integer -> a -> [a] -> [a]
+padLeft n x ys = reverse (padRight n x (reverse ys))
+
+padRight :: Integer -> a -> [a] -> [a]
+padRight n x ys =
+  if n <= 0
+    then ys
+    else case ys of
+           [] -> x : padRight (n - 1) x ys
+           y:zs -> y : padRight (n - 1) x zs
+
+runParser :: ReadP.ReadP a -> String -> Maybe a
+runParser p s =
+  Maybe.listToMaybe
+    (Maybe.mapMaybe
+       (\(x, t) ->
+          if null t
+            then Just x
+            else Nothing)
+       (ReadP.readP_to_S p s))
+
+sBetween :: ShowS -> ShowS -> (anything -> ShowS) -> anything -> ShowS
+sBetween left right render it = left . render it . right
+
+sSeparated :: ShowS -> (element -> ShowS) -> [element] -> ShowS
+sSeparated separator render elements =
+  case elements of
+    [] -> id
+    [element] -> render element
+    element:rest ->
+      render element . separator . sSeparated separator render rest
+
+sSeparatedBetween ::
+     ShowS -> ShowS -> ShowS -> (element -> ShowS) -> [element] -> ShowS
+sSeparatedBetween left right separator render elements =
+  sBetween left right (sSeparated separator render) elements
+
+toBase :: Integer -> (Integer -> Maybe Char) -> Integer -> String
+toBase b f n =
+  if n == 0
+    then [Maybe.fromJust (f n)]
+    else reverse (toBase' b f n)
+
+toBase' :: Integer -> (Integer -> Maybe Char) -> Integer -> String
+toBase' b f n =
+  case quotRem n b of
+    (0, 0) -> ""
+    (q, r) -> Maybe.fromJust (f r) : toBase' b f q
+
+toHexadecimal :: Integer -> String
+toHexadecimal n = toBase 16 toHexadecimalDigit n
+
+toHexadecimalDigit :: Integer -> Maybe Char
+toHexadecimalDigit n =
+  case n of
+    0 -> Just '0'
+    1 -> Just '1'
+    2 -> Just '2'
+    3 -> Just '3'
+    4 -> Just '4'
+    5 -> Just '5'
+    6 -> Just '6'
+    7 -> Just '7'
+    8 -> Just '8'
+    9 -> Just '9'
+    10 -> Just 'a'
+    11 -> Just 'b'
+    12 -> Just 'c'
+    13 -> Just 'd'
+    14 -> Just 'e'
+    15 -> Just 'f'
+    _ -> Nothing
diff --git a/src/test/Main.hs b/src/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/test/Main.hs
@@ -0,0 +1,353 @@
+import qualified Control.Monad as Monad
+import qualified Derulo
+import qualified System.Exit as Exit
+import qualified Test.HUnit as Test
+
+main :: IO ()
+main = do
+  counts <- Test.runTestTT $ Test.TestList
+    [ Derulo.readJSON " null " Test.~?= Just Derulo.Null
+    , Derulo.showJSON Derulo.Null Test.~?= "null"
+    , Derulo.readJSON "null" Test.~?= Just Derulo.Null
+    , Derulo.readJSON "true" Test.~?= Just (Derulo.Boolean True)
+    , Derulo.readJSON "false" Test.~?= Just (Derulo.Boolean False)
+    , Derulo.readJSON "0e0" Test.~?= Just (Derulo.Number 0 0)
+    , Derulo.readJSON "12e34" Test.~?= Just (Derulo.Number 12 34)
+    , Derulo.readJSON "-12e-34" Test.~?= Just (Derulo.Number (-12) (-34))
+    , Derulo.readJSON "\"\"" Test.~?= Just (Derulo.String "")
+    , Derulo.readJSON "\"js\"" Test.~?= Just (Derulo.String "js")
+    , Derulo.readJSON "\"\\\"\\\\\\b\\f\\n\\r\\t\"" Test.~?= Just (Derulo.String "\"\\\b\f\n\r\t")
+    , Derulo.readJSON "\"\\u001f\"" Test.~?= Just (Derulo.String "\x1f")
+    , Derulo.readJSON "[]" Test.~?= Just (Derulo.Array [])
+    , Derulo.readJSON "[null]" Test.~?= Just (Derulo.Array [Derulo.Null])
+    , Derulo.readJSON "[true,false]" Test.~?= Just (Derulo.Array [Derulo.Boolean True, Derulo.Boolean False])
+    , Derulo.readJSON "{}" Test.~?= Just (Derulo.Object [])
+    , Derulo.readJSON "{\"\":null}" Test.~?= Just (Derulo.Object [("", Derulo.Null)])
+    , Derulo.readJSON "{\"t\":true,\"f\":false}" Test.~?= Just (Derulo.Object [("t", Derulo.Boolean True), ("f", Derulo.Boolean False)])
+    , Derulo.showJSON Derulo.Null Test.~?= "null"
+    , Derulo.showJSON (Derulo.Boolean True) Test.~?= "true"
+    , Derulo.showJSON (Derulo.Boolean False) Test.~?= "false"
+    , Derulo.showJSON (Derulo.Number 0 0) Test.~?= "0e0"
+    , Derulo.showJSON (Derulo.Number 12 34) Test.~?= "12e34"
+    , Derulo.showJSON (Derulo.Number (-12) (-34)) Test.~?= "-12e-34"
+    , Derulo.showJSON (Derulo.String "") Test.~?= "\"\""
+    , Derulo.showJSON (Derulo.String "js") Test.~?= "\"js\""
+    , Derulo.showJSON (Derulo.String "\"\\\b\f\n\r\t") Test.~?= "\"\\\"\\\\\\b\\f\\n\\r\\t\""
+    , Derulo.showJSON (Derulo.String "\x1f") Test.~?= "\"\\u001f\""
+    , Derulo.showJSON (Derulo.Array []) Test.~?= "[]"
+    , Derulo.showJSON (Derulo.Array [Derulo.Null]) Test.~?= "[null]"
+    , Derulo.showJSON (Derulo.Array [Derulo.Boolean True, Derulo.Boolean False]) Test.~?= "[true,false]"
+    , Derulo.showJSON (Derulo.Object []) Test.~?= "{}"
+    , Derulo.showJSON (Derulo.Object [("", Derulo.Null)]) Test.~?= "{\"\":null}"
+    , Derulo.showJSON (Derulo.Object [("t", Derulo.Boolean True), ("f", Derulo.Boolean False)]) Test.~?= "{\"t\":true,\"f\":false}"
+    , Derulo.readJSON "[123.456e-789]" Test.~?= Just (Derulo.Array [Derulo.Number 123456 (-792)])
+    , Derulo.readJSON "[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]" Test.~?= Just (Derulo.Array [Derulo.Number (-4) 669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999005])
+    , Derulo.readJSON "[-1e+9999]" Test.~?= Just (Derulo.Array [Derulo.Number (-1) 9999])
+    , Derulo.readJSON "[1.5e+9999]" Test.~?= Just (Derulo.Array [Derulo.Number 15 9998])
+    , Derulo.readJSON "[-123123e100000]" Test.~?= Just (Derulo.Array [Derulo.Number (-123123) 100000])
+    , Derulo.readJSON "[123123e100000]" Test.~?= Just (Derulo.Array [Derulo.Number 123123 100000])
+    , Derulo.readJSON "[123e-10000000]" Test.~?= Just (Derulo.Array [Derulo.Number 123 (-10000000)])
+    , Derulo.readJSON "[-123123123123123123123123123123]" Test.~?= Just (Derulo.Array [Derulo.Number (-123123123123123123123123123123) 0])
+    , Derulo.readJSON "[100000000000000000000]" Test.~?= Just (Derulo.Array [Derulo.Number 100000000000000000000 0])
+    , Derulo.readJSON "[-237462374673276894279832749832423479823246327846]" Test.~?= Just (Derulo.Array [Derulo.Number (-237462374673276894279832749832423479823246327846) 0])
+    , Derulo.readJSON "{\"\\uDFAA\":0}" Test.~?= Just (Derulo.Object [("\57258", Derulo.Number 0 0)])
+    , Derulo.readJSON "[\"\\uDADA\"]" Test.~?= Just (Derulo.Array [Derulo.String "\56026"])
+    , Derulo.readJSON "[\"\\uD888\\u1234\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55432\4660"])
+    , Derulo.readJSON "[\"\\uD800\\n\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296\n"])
+    , Derulo.readJSON "[\"\\uDd1ea\"]" Test.~?= Just (Derulo.Array [Derulo.String "\56606a"])
+    , Derulo.readJSON "[\"\\uD800\\uD800\\n\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296\55296\n"])
+    , Derulo.readJSON "[\"\\ud800\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296"])
+    , Derulo.readJSON "[\"\\ud800abc\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296abc"])
+    , Derulo.readJSON "[\"\\uDd1e\\uD834\"]" Test.~?= Just (Derulo.Array [Derulo.String "\56606\55348"])
+    , Derulo.readJSON "[\"\\uDFAA\"]" Test.~?= Just (Derulo.Array [Derulo.String "\57258"])
+    , Derulo.readJSON "\65279{}" Test.~?= Nothing
+    , Derulo.readJSON "[1 true]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\": 1]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\"]," Test.~?= Nothing
+    , Derulo.readJSON "[,1]" Test.~?= Nothing
+    , Derulo.readJSON "[1,,2]" Test.~?= Nothing
+    , Derulo.readJSON "[\"x\",,]" Test.~?= Nothing
+    , Derulo.readJSON "[\"x\"]]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\",]" Test.~?= Nothing
+    , Derulo.readJSON "[\"x\"" Test.~?= Nothing
+    , Derulo.readJSON "[x" Test.~?= Nothing
+    , Derulo.readJSON "[3[4]]" Test.~?= Nothing
+    , Derulo.readJSON "[1:2]" Test.~?= Nothing
+    , Derulo.readJSON "[,]" Test.~?= Nothing
+    , Derulo.readJSON "[-]" Test.~?= Nothing
+    , Derulo.readJSON "[   , \"\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"a\",\n4\n,1," Test.~?= Nothing
+    , Derulo.readJSON "[1,]" Test.~?= Nothing
+    , Derulo.readJSON "[1,,]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\va\"\\f]" Test.~?= Nothing
+    , Derulo.readJSON "[*]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\"" Test.~?= Nothing
+    , Derulo.readJSON "[1," Test.~?= Nothing
+    , Derulo.readJSON "[1,\n1\n,1" Test.~?= Nothing
+    , Derulo.readJSON "[{}" Test.~?= Nothing
+    , Derulo.readJSON "[fals]" Test.~?= Nothing
+    , Derulo.readJSON "[nul]" Test.~?= Nothing
+    , Derulo.readJSON "[tru]" Test.~?= Nothing
+    , Derulo.readJSON "123\NUL" Test.~?= Nothing
+    , Derulo.readJSON "[++1234]" Test.~?= Nothing
+    , Derulo.readJSON "[+1]" Test.~?= Nothing
+    , Derulo.readJSON "[+Inf]" Test.~?= Nothing
+    , Derulo.readJSON "[-01]" Test.~?= Nothing
+    , Derulo.readJSON "[-1.0.]" Test.~?= Nothing
+    , Derulo.readJSON "[-2.]" Test.~?= Nothing
+    , Derulo.readJSON "[-NaN]" Test.~?= Nothing
+    , Derulo.readJSON "[.-1]" Test.~?= Nothing
+    , Derulo.readJSON "[.2e-3]" Test.~?= Nothing
+    , Derulo.readJSON "[0.1.2]" Test.~?= Nothing
+    , Derulo.readJSON "[0.3e+]" Test.~?= Nothing
+    , Derulo.readJSON "[0.3e]" Test.~?= Nothing
+    , Derulo.readJSON "[0.e1]" Test.~?= Nothing
+    , Derulo.readJSON "[0E+]" Test.~?= Nothing
+    , Derulo.readJSON "[0E]" Test.~?= Nothing
+    , Derulo.readJSON "[0e+]" Test.~?= Nothing
+    , Derulo.readJSON "[0e]" Test.~?= Nothing
+    , Derulo.readJSON "[1.0e+]" Test.~?= Nothing
+    , Derulo.readJSON "[1.0e-]" Test.~?= Nothing
+    , Derulo.readJSON "[1.0e]" Test.~?= Nothing
+    , Derulo.readJSON "[1 000.0]" Test.~?= Nothing
+    , Derulo.readJSON "[1eE2]" Test.~?= Nothing
+    , Derulo.readJSON "[2.e+3]" Test.~?= Nothing
+    , Derulo.readJSON "[2.e-3]" Test.~?= Nothing
+    , Derulo.readJSON "[2.e3]" Test.~?= Nothing
+    , Derulo.readJSON "[9.e+]" Test.~?= Nothing
+    , Derulo.readJSON "[Inf]" Test.~?= Nothing
+    , Derulo.readJSON "[NaN]" Test.~?= Nothing
+    , Derulo.readJSON "[\65297]" Test.~?= Nothing
+    , Derulo.readJSON "[1+2]" Test.~?= Nothing
+    , Derulo.readJSON "[0x1]" Test.~?= Nothing
+    , Derulo.readJSON "[0x42]" Test.~?= Nothing
+    , Derulo.readJSON "[Infinity]" Test.~?= Nothing
+    , Derulo.readJSON "[0e+-1]" Test.~?= Nothing
+    , Derulo.readJSON "[-123.123foo]" Test.~?= Nothing
+    , Derulo.readJSON "[-Infinity]" Test.~?= Nothing
+    , Derulo.readJSON "[-foo]" Test.~?= Nothing
+    , Derulo.readJSON "[- 1]" Test.~?= Nothing
+    , Derulo.readJSON "[-012]" Test.~?= Nothing
+    , Derulo.readJSON "[-.123]" Test.~?= Nothing
+    , Derulo.readJSON "[-1x]" Test.~?= Nothing
+    , Derulo.readJSON "[1ea]" Test.~?= Nothing
+    , Derulo.readJSON "[1.]" Test.~?= Nothing
+    , Derulo.readJSON "[.123]" Test.~?= Nothing
+    , Derulo.readJSON "[1.2a-3]" Test.~?= Nothing
+    , Derulo.readJSON "[1.8011670033376514H-308]" Test.~?= Nothing
+    , Derulo.readJSON "[012]" Test.~?= Nothing
+    , Derulo.readJSON "[\"x\", truth]" Test.~?= Nothing
+    , Derulo.readJSON "{[: \"x\"}\n" Test.~?= Nothing
+    , Derulo.readJSON "{\"x\", null}" Test.~?= Nothing
+    , Derulo.readJSON "{\"x\"::\"b\"}" Test.~?= Nothing
+    , Derulo.readJSON "{\127464\127469}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"a\" 123}" Test.~?= Nothing
+    , Derulo.readJSON "{key: 'value'}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\" b}" Test.~?= Nothing
+    , Derulo.readJSON "{:\"b\"}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\" \"b\"}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\"" Test.~?= Nothing
+    , Derulo.readJSON "{1:1}" Test.~?= Nothing
+    , Derulo.readJSON "{9999E9999:1}" Test.~?= Nothing
+    , Derulo.readJSON "{null:null,null:null}" Test.~?= Nothing
+    , Derulo.readJSON "{\"id\":0,,,,,}" Test.~?= Nothing
+    , Derulo.readJSON "{'a':0}" Test.~?= Nothing
+    , Derulo.readJSON "{\"id\":0,}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}/**/" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}/**//" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}//" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}/" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\",,\"c\":\"d\"}" Test.~?= Nothing
+    , Derulo.readJSON "{a: \"b\"}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"a" Test.~?= Nothing
+    , Derulo.readJSON "{ \"foo\" : \"bar\", \"a\" }" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}#" Test.~?= Nothing
+    , Derulo.readJSON " " Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD800\\\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD800\\u\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD800\\u1\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD800\\u1x\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\233]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\\NUL\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\x00\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\\\\\\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\\t\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\\127744\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\u00A\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD834\\uDd\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uD800\\uD800\\x\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\a\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\uqqqq\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\\u0020\"asd\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\\n]" Test.~?= Nothing
+    , Derulo.readJSON "\"" Test.~?= Nothing
+    , Derulo.readJSON "['single quote']" Test.~?= Nothing
+    , Derulo.readJSON "abc" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\" Test.~?= Nothing
+    , Derulo.readJSON "[\"a\NULa\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"new\nline\"]" Test.~?= Nothing
+    , Derulo.readJSON "[\"\t\"]" Test.~?= Nothing
+    , Derulo.readJSON "\"\\UA66D\"" Test.~?= Nothing
+    , Derulo.readJSON "\"\"x" Test.~?= Nothing
+    , Derulo.readJSON "[\8288]" Test.~?= Nothing
+    , Derulo.readJSON "\65279" Test.~?= Nothing
+    , Derulo.readJSON "<.>" Test.~?= Nothing
+    , Derulo.readJSON "[<null>]" Test.~?= Nothing
+    , Derulo.readJSON "[1]x" Test.~?= Nothing
+    , Derulo.readJSON "[1]]" Test.~?= Nothing
+    , Derulo.readJSON "[\"asd]" Test.~?= Nothing
+    , Derulo.readJSON "a\229" Test.~?= Nothing
+    , Derulo.readJSON "[True]" Test.~?= Nothing
+    , Derulo.readJSON "1]" Test.~?= Nothing
+    , Derulo.readJSON "{\"x\": true," Test.~?= Nothing
+    , Derulo.readJSON "[][]" Test.~?= Nothing
+    , Derulo.readJSON "]" Test.~?= Nothing
+    , Derulo.readJSON "[" Test.~?= Nothing
+    , Derulo.readJSON "" Test.~?= Nothing
+    , Derulo.readJSON "[\NUL]" Test.~?= Nothing
+    , Derulo.readJSON "2@" Test.~?= Nothing
+    , Derulo.readJSON "{}}" Test.~?= Nothing
+    , Derulo.readJSON "{\"\":" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":/*comment*/\"b\"}" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\": true} \"x\"" Test.~?= Nothing
+    , Derulo.readJSON "['" Test.~?= Nothing
+    , Derulo.readJSON "[," Test.~?= Nothing
+    , Derulo.readJSON "[{" Test.~?= Nothing
+    , Derulo.readJSON "[\"a" Test.~?= Nothing
+    , Derulo.readJSON "[\"a\"" Test.~?= Nothing
+    , Derulo.readJSON "{" Test.~?= Nothing
+    , Derulo.readJSON "{]" Test.~?= Nothing
+    , Derulo.readJSON "{," Test.~?= Nothing
+    , Derulo.readJSON "{[" Test.~?= Nothing
+    , Derulo.readJSON "{\"a" Test.~?= Nothing
+    , Derulo.readJSON "{'a'" Test.~?= Nothing
+    , Derulo.readJSON "[\"\\{[\"\\{[\"\\{[\"\\{" Test.~?= Nothing
+    , Derulo.readJSON "*" Test.~?= Nothing
+    , Derulo.readJSON "{\"a\":\"b\"}#{}" Test.~?= Nothing
+    , Derulo.readJSON "[\\u000A\"\"]" Test.~?= Nothing
+    , Derulo.readJSON "[1" Test.~?= Nothing
+    , Derulo.readJSON "[ false, nul" Test.~?= Nothing
+    , Derulo.readJSON "[ true, fals" Test.~?= Nothing
+    , Derulo.readJSON "[ false, tru" Test.~?= Nothing
+    , Derulo.readJSON "{\"asd\":\"asd\"" Test.~?= Nothing
+    , Derulo.readJSON "\229" Test.~?= Nothing
+    , Derulo.readJSON "[\8288]" Test.~?= Nothing
+    , Derulo.readJSON "[\f]" Test.~?= Nothing
+    , Derulo.readJSON "[[]   ]" Test.~?= Just (Derulo.Array [Derulo.Array []])
+    , Derulo.readJSON "[\"\"]" Test.~?= Just (Derulo.Array [Derulo.String ""])
+    , Derulo.readJSON "[]" Test.~?= Just (Derulo.Array [])
+    , Derulo.readJSON "[\"a\"]" Test.~?= Just (Derulo.Array [Derulo.String "a"])
+    , Derulo.readJSON "[false]" Test.~?= Just (Derulo.Array [Derulo.Boolean False])
+    , Derulo.readJSON "[null, 1, \"1\", {}]" Test.~?= Just (Derulo.Array [Derulo.Null, Derulo.Number 1 0, Derulo.String "1", Derulo.Object []])
+    , Derulo.readJSON "[null]" Test.~?= Just (Derulo.Array [Derulo.Null])
+    , Derulo.readJSON "[1\n]" Test.~?= Just (Derulo.Array [Derulo.Number 1 0])
+    , Derulo.readJSON " [1]" Test.~?= Just (Derulo.Array [Derulo.Number 1 0])
+    , Derulo.readJSON "[1,null,null,null,2]" Test.~?= Just (Derulo.Array [Derulo.Number 1 0, Derulo.Null, Derulo.Null, Derulo.Null, Derulo.Number 2 0])
+    , Derulo.readJSON "[2] " Test.~?= Just (Derulo.Array [Derulo.Number 2 0])
+    , Derulo.readJSON "[123e65]" Test.~?= Just (Derulo.Array [Derulo.Number 123 65])
+    , Derulo.readJSON "[0e+1]" Test.~?= Just (Derulo.Array [Derulo.Number 0 1])
+    , Derulo.readJSON "[0e1]" Test.~?= Just (Derulo.Array [Derulo.Number 0 1])
+    , Derulo.readJSON "[ 4]" Test.~?= Just (Derulo.Array [Derulo.Number 4 0])
+    , Derulo.readJSON "[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]\n" Test.~?= Just (Derulo.Array [Derulo.Number (-1) (-78)])
+    , Derulo.readJSON "[20e1]" Test.~?= Just (Derulo.Array [Derulo.Number 20 1])
+    , Derulo.readJSON "[-0]" Test.~?= Just (Derulo.Array [Derulo.Number 0 0])
+    , Derulo.readJSON "[-123]" Test.~?= Just (Derulo.Array [Derulo.Number (-123) 0])
+    , Derulo.readJSON "[-1]" Test.~?= Just (Derulo.Array [Derulo.Number (-1) 0])
+    , Derulo.readJSON "[-0]" Test.~?= Just (Derulo.Array [Derulo.Number 0 0])
+    , Derulo.readJSON "[1E22]" Test.~?= Just (Derulo.Array [Derulo.Number 1 22])
+    , Derulo.readJSON "[1E-2]" Test.~?= Just (Derulo.Array [Derulo.Number 1 (-2)])
+    , Derulo.readJSON "[1E+2]" Test.~?= Just (Derulo.Array [Derulo.Number 1 2])
+    , Derulo.readJSON "[123e45]" Test.~?= Just (Derulo.Array [Derulo.Number 123 45])
+    , Derulo.readJSON "[123.456e78]" Test.~?= Just (Derulo.Array [Derulo.Number 123456 75])
+    , Derulo.readJSON "[1e-2]" Test.~?= Just (Derulo.Array [Derulo.Number 1 (-2)])
+    , Derulo.readJSON "[1e+2]" Test.~?= Just (Derulo.Array [Derulo.Number 1 2])
+    , Derulo.readJSON "[123]" Test.~?= Just (Derulo.Array [Derulo.Number 123 0])
+    , Derulo.readJSON "[123.456789]" Test.~?= Just (Derulo.Array [Derulo.Number 123456789 (-6)])
+    , Derulo.readJSON "{\"asd\":\"sdf\", \"dfg\":\"fgh\"}" Test.~?= Just (Derulo.Object [("asd", Derulo.String "sdf"), ("dfg", Derulo.String "fgh")])
+    , Derulo.readJSON "{\"asd\":\"sdf\"}" Test.~?= Just (Derulo.Object [("asd", Derulo.String "sdf")])
+    , Derulo.readJSON "{\"a\":\"b\",\"a\":\"c\"}" Test.~?= Just (Derulo.Object [("a", Derulo.String "b"), ("a", Derulo.String "c")])
+    , Derulo.readJSON "{\"a\":\"b\",\"a\":\"b\"}" Test.~?= Just (Derulo.Object [("a", Derulo.String "b"), ("a", Derulo.String "b")])
+    , Derulo.readJSON "{}" Test.~?= Just (Derulo.Object [])
+    , Derulo.readJSON "{\"\":0}" Test.~?= Just (Derulo.Object [("", Derulo.Number 0 0)])
+    , Derulo.readJSON "{\"foo\\u0000bar\": 42}" Test.~?= Just (Derulo.Object [("foo\NULbar", Derulo.Number 42 0)])
+    , Derulo.readJSON "{ \"min\": -1.0e+28, \"max\": 1.0e+28 }" Test.~?= Just (Derulo.Object [("min", Derulo.Number (-10) 27), ("max", Derulo.Number 10 27)])
+    , Derulo.readJSON "{\"x\":[{\"id\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}], \"id\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}" Test.~?= Just (Derulo.Object [("x", Derulo.Array [Derulo.Object [("id", Derulo.String "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")]]), ("id", Derulo.String "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")])
+    , Derulo.readJSON "{\"a\":[]}" Test.~?= Just (Derulo.Object [("a", Derulo.Array [])])
+    , Derulo.readJSON "{\"title\":\"\\u041f\\u043e\\u043b\\u0442\\u043e\\u0440\\u0430 \\u0417\\u0435\\u043c\\u043b\\u0435\\u043a\\u043e\\u043f\\u0430\" }" Test.~?= Just (Derulo.Object [("title", Derulo.String "\1055\1086\1083\1090\1086\1088\1072 \1047\1077\1084\1083\1077\1082\1086\1087\1072")])
+    , Derulo.readJSON "{\n\"a\": \"b\"\n}" Test.~?= Just (Derulo.Object [("a", Derulo.String "b")])
+    , Derulo.readJSON "[\"\\u0060\\u012a\\u12AB\"]" Test.~?= Just (Derulo.Array [Derulo.String "`\298\4779"])
+    , Derulo.readJSON "[\"\\uD801\\udc37\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55297\56375"])
+    , Derulo.readJSON "[\"\\ud83d\\ude39\\ud83d\\udc8d\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55357\56889\55357\56461"])
+    , Derulo.readJSON "[\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"]" Test.~?= Just (Derulo.Array [Derulo.String "\"\\/\b\f\n\r\t"])
+    , Derulo.readJSON "[\"\\\\u0000\"]" Test.~?= Just (Derulo.Array [Derulo.String "\\u0000"])
+    , Derulo.readJSON "[\"\\\"\"]" Test.~?= Just (Derulo.Array [Derulo.String "\""])
+    , Derulo.readJSON "[\"a/*b*/c/*d//e\"]" Test.~?= Just (Derulo.Array [Derulo.String "a/*b*/c/*d//e"])
+    , Derulo.readJSON "[\"\\\\a\"]" Test.~?= Just (Derulo.Array [Derulo.String "\\a"])
+    , Derulo.readJSON "[\"\\\\n\"]" Test.~?= Just (Derulo.Array [Derulo.String "\\n"])
+    , Derulo.readJSON "[\"\\u0012\"]" Test.~?= Just (Derulo.Array [Derulo.String "\DC2"])
+    , Derulo.readJSON "[\"\\uFFFF\"]" Test.~?= Just (Derulo.Array [Derulo.String "\65535"])
+    , Derulo.readJSON "[\"asd\"]" Test.~?= Just (Derulo.Array [Derulo.String "asd"])
+    , Derulo.readJSON "[ \"asd\"]" Test.~?= Just (Derulo.Array [Derulo.String "asd"])
+    , Derulo.readJSON "[\"\\uDBFF\\uDFFF\"]" Test.~?= Just (Derulo.Array [Derulo.String "\56319\57343"])
+    , Derulo.readJSON "[\"new\\u00A0line\"]" Test.~?= Just (Derulo.Array [Derulo.String "new\160line"])
+    , Derulo.readJSON "[\"\1114111\"]" Test.~?= Just (Derulo.Array [Derulo.String "\1114111"])
+    , Derulo.readJSON "[\"\114687\"]" Test.~?= Just (Derulo.Array [Derulo.String "\114687"])
+    , Derulo.readJSON "[\"\65535\"]" Test.~?= Just (Derulo.Array [Derulo.String "\65535"])
+    , Derulo.readJSON "[\"\\u0000\"]" Test.~?= Just (Derulo.Array [Derulo.String "\NUL"])
+    , Derulo.readJSON "[\"\\u002c\"]" Test.~?= Just (Derulo.Array [Derulo.String ","])
+    , Derulo.readJSON "[\"\960\"]" Test.~?= Just (Derulo.Array [Derulo.String "\960"])
+    , Derulo.readJSON "[\"asd \"]" Test.~?= Just (Derulo.Array [Derulo.String "asd "])
+    , Derulo.readJSON "\" \"" Test.~?= Just (Derulo.String " ")
+    , Derulo.readJSON "[\"\\uD834\\uDd1e\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55348\56606"])
+    , Derulo.readJSON "[\"\\u0821\"]" Test.~?= Just (Derulo.Array [Derulo.String "\2081"])
+    , Derulo.readJSON "[\"\\u0123\"]" Test.~?= Just (Derulo.Array [Derulo.String "\291"])
+    , Derulo.readJSON "[\"\8232\"]" Test.~?= Just (Derulo.Array [Derulo.String "\8232"])
+    , Derulo.readJSON "[\"\8233\"]" Test.~?= Just (Derulo.Array [Derulo.String "\8233"])
+    , Derulo.readJSON "[\"\\u0061\\u30af\\u30EA\\u30b9\"]" Test.~?= Just (Derulo.Array [Derulo.String "a\12463\12522\12473"])
+    , Derulo.readJSON "[\"new\\u000Aline\"]" Test.~?= Just (Derulo.Array [Derulo.String "new\nline"])
+    , Derulo.readJSON "[\"\DEL\"]" Test.~?= Just (Derulo.Array [Derulo.String "\DEL"])
+    , Derulo.readJSON "[\"\\uA66D\"]" Test.~?= Just (Derulo.Array [Derulo.String "\42605"])
+    , Derulo.readJSON "[\"\\u005C\"]" Test.~?= Just (Derulo.Array [Derulo.String "\\"])
+    , Derulo.readJSON "[\"\9026\12852\9026\"]" Test.~?= Just (Derulo.Array [Derulo.String "\9026\12852\9026"])
+    , Derulo.readJSON "[\"\\uDBFF\\uDFFE\"]" Test.~?= Just (Derulo.Array [Derulo.String "\56319\57342"])
+    , Derulo.readJSON "[\"\\uD83F\\uDFFE\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55359\57342"])
+    , Derulo.readJSON "[\"\\u200B\"]" Test.~?= Just (Derulo.Array [Derulo.String "\8203"])
+    , Derulo.readJSON "[\"\\u2064\"]" Test.~?= Just (Derulo.Array [Derulo.String "\8292"])
+    , Derulo.readJSON "[\"\\uFDD0\"]" Test.~?= Just (Derulo.Array [Derulo.String "\64976"])
+    , Derulo.readJSON "[\"\\uFFFE\"]" Test.~?= Just (Derulo.Array [Derulo.String "\65534"])
+    , Derulo.readJSON "[\"\\u0022\"]" Test.~?= Just (Derulo.Array [Derulo.String "\""])
+    , Derulo.readJSON "[\"\8364\119070\"]" Test.~?= Just (Derulo.Array [Derulo.String "\8364\119070"])
+    , Derulo.readJSON "[\"a\DELa\"]" Test.~?= Just (Derulo.Array [Derulo.String "a\DELa"])
+    , Derulo.readJSON "false" Test.~?= Just (Derulo.Boolean False)
+    , Derulo.readJSON "42" Test.~?= Just (Derulo.Number 42 0)
+    , Derulo.readJSON "-0.1" Test.~?= Just (Derulo.Number (-1) (-1))
+    , Derulo.readJSON "null" Test.~?= Just Derulo.Null
+    , Derulo.readJSON "\"asd\"" Test.~?= Just (Derulo.String "asd")
+    , Derulo.readJSON "true" Test.~?= Just (Derulo.Boolean True)
+    , Derulo.readJSON "\"\"" Test.~?= Just (Derulo.String "")
+    , Derulo.readJSON "[\"a\"]\n" Test.~?= Just (Derulo.Array [Derulo.String "a"])
+    , Derulo.readJSON "[true]" Test.~?= Just (Derulo.Array [Derulo.Boolean True])
+    , Derulo.readJSON " [] " Test.~?= Just (Derulo.Array [])
+    , Derulo.readJSON "[1.0]" Test.~?= Just (Derulo.Array [Derulo.Number 10 (-1)])
+    , Derulo.readJSON "[1.000000000000000005]" Test.~?= Just (Derulo.Array [Derulo.Number 1000000000000000005 (-18)])
+    , Derulo.readJSON "[1000000000000000]\n" Test.~?= Just (Derulo.Array [Derulo.Number 1000000000000000 0])
+    , Derulo.readJSON "[10000000000000000999]" Test.~?= Just (Derulo.Array [Derulo.Number 10000000000000000999 0])
+    , Derulo.readJSON "[1E-999]" Test.~?= Just (Derulo.Array [Derulo.Number 1 (-999)])
+    , Derulo.readJSON "[1E6]" Test.~?= Just (Derulo.Array [Derulo.Number 1 6])
+    , Derulo.readJSON "{\"\233\":\"NFC\",\"e\769\":\"NFD\"}" Test.~?= Just (Derulo.Object [("\233", Derulo.String "NFC"), ("e\769", Derulo.String "NFD")])
+    , Derulo.readJSON "{\"e\769\":\"NFD\",\"\233\":\"NFC\"}" Test.~?= Just (Derulo.Object [("e\769", Derulo.String "NFD"), ("\233", Derulo.String "NFC")])
+    , Derulo.readJSON "{\"a\":1,\"a\":2}" Test.~?= Just (Derulo.Object [("a", Derulo.Number 1 0), ("a", Derulo.Number 2 0)])
+    , Derulo.readJSON "{\"a\":1,\"a\":1}" Test.~?= Just (Derulo.Object [("a", Derulo.Number 1 0), ("a", Derulo.Number 1 0)])
+    , Derulo.readJSON "{\"a\":0, \"a\":-0}\n" Test.~?= Just (Derulo.Object [("a", Derulo.Number 0 0), ("a", Derulo.Number 0 0)])
+    , Derulo.readJSON "[\"\\uD800\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296"])
+    , Derulo.readJSON "[\"\\uD800\\uD800\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296\55296"])
+    , Derulo.readJSON "[\"\\uD800\\uD800\\uD800\"]" Test.~?= Just (Derulo.Array [Derulo.String "\55296\55296\55296"])
+    , Derulo.readJSON "[\"A\\u0000B\"]" Test.~?= Just (Derulo.Array [Derulo.String "A\NULB"])
+    ]
+
+  let
+    hasErrors = Test.errors counts /= 0
+    hasFailures = Test.failures counts /= 0
+  Monad.when (hasErrors || hasFailures) Exit.exitFailure
diff --git a/stack.yaml b/stack.yaml
deleted file mode 100644
--- a/stack.yaml
+++ /dev/null
@@ -1,1 +0,0 @@
-resolver: lts-15.4
diff --git a/tests/Main.hs b/tests/Main.hs
deleted file mode 100644
--- a/tests/Main.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-import qualified Test.DocTest as Doctest
-
-main :: IO ()
-main = Doctest.doctest ["library"]
