diff --git a/Data/Aeson/Encoding/Builder.hs b/Data/Aeson/Encoding/Builder.hs
--- a/Data/Aeson/Encoding/Builder.hs
+++ b/Data/Aeson/Encoding/Builder.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
 
 -- |
 -- Module:      Data.Aeson.Encoding.Builder
diff --git a/Data/Aeson/Parser.hs b/Data/Aeson/Parser.hs
--- a/Data/Aeson/Parser.hs
+++ b/Data/Aeson/Parser.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 -- |
 -- Module:      Data.Aeson.Parser
 -- Copyright:   (c) 2012-2016 Bryan O'Sullivan
diff --git a/Data/Aeson/Types.hs b/Data/Aeson/Types.hs
--- a/Data/Aeson/Types.hs
+++ b/Data/Aeson/Types.hs
@@ -36,6 +36,8 @@
     , ToJSON(..)
     , KeyValue(..)
     , modifyFailure
+    , parserThrowError
+    , parserCatchError
 
     -- ** Keys for maps
     , ToJSONKey(..)
diff --git a/Data/Aeson/Types/FromJSON.hs b/Data/Aeson/Types/FromJSON.hs
--- a/Data/Aeson/Types/FromJSON.hs
+++ b/Data/Aeson/Types/FromJSON.hs
@@ -1539,8 +1539,8 @@
         FromJSONKeyTextParser f -> withObject "Map k v" $
             H.foldrWithKey (\k v m -> M.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure M.empty)
         FromJSONKeyValue f -> withArray "Map k v" $ \arr ->
-            M.fromList <$> (Tr.sequence .
-                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)
+            fmap M.fromList . Tr.sequence .
+                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr
     {-# INLINE liftParseJSON #-}
 
 instance (FromJSONKey k, Ord k, FromJSON v) => FromJSON (M.Map k v) where
@@ -1619,8 +1619,8 @@
         FromJSONKeyTextParser f -> withObject "HashMap k v" $
             H.foldrWithKey (\k v m -> H.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure H.empty)
         FromJSONKeyValue f -> withArray "Map k v" $ \arr ->
-            H.fromList <$> (Tr.sequence .
-                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)
+            fmap H.fromList . Tr.sequence .
+                zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr
       where
         uc :: Parser (H.HashMap Text v) -> Parser (H.HashMap k v)
         uc = unsafeCoerce
diff --git a/Data/Aeson/Types/Internal.hs b/Data/Aeson/Types/Internal.hs
--- a/Data/Aeson/Types/Internal.hs
+++ b/Data/Aeson/Types/Internal.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE Rank2Types #-}
 #if __GLASGOW_HASKELL__ >= 800
@@ -43,6 +44,8 @@
     , parseEither
     , parseMaybe
     , modifyFailure
+    , parserThrowError
+    , parserCatchError
     , formatError
     , (<?>)
     -- * Constructors and accessors
@@ -92,6 +95,7 @@
 import Data.Time.Format (FormatTime)
 import Data.Typeable (Typeable)
 import Data.Vector (Vector)
+import GHC.Generics (Generic)
 import qualified Control.Monad.Fail as Fail
 import qualified Data.HashMap.Strict as H
 import qualified Data.Scientific as S
@@ -342,7 +346,7 @@
            | Number !Scientific
            | Bool !Bool
            | Null
-             deriving (Eq, Read, Show, Typeable, Data)
+             deriving (Eq, Read, Show, Typeable, Data, Generic)
 
 -- | A newtype wrapper for 'UTCTime' that uses the same non-standard
 -- serialization format as Microsoft .NET, whose
@@ -505,7 +509,22 @@
 --
 -- Since 0.6.2.0
 modifyFailure :: (String -> String) -> Parser a -> Parser a
-modifyFailure f (Parser p) = Parser $ \path kf ks -> p path (\p' m -> kf p' (f m)) ks
+modifyFailure f (Parser p) = Parser $ \path kf ks ->
+    p path (\p' m -> kf p' (f m)) ks
+
+-- | Throw a parser error with an additional path.
+--
+-- @since 1.2.1.0
+parserThrowError :: JSONPath -> String -> Parser a
+parserThrowError path' msg = Parser $ \path kf _ks ->
+    kf (reverse path ++ path') msg
+
+-- | A handler function to handle previous errors and return to normal execution.
+--
+-- @since 1.2.1.0
+parserCatchError :: Parser a -> (JSONPath -> String -> Parser a) -> Parser a
+parserCatchError (Parser p) handler = Parser $ \path kf ks ->
+    p path (\e msg -> runParser (handler e msg) path kf ks) ks
 
 --------------------------------------------------------------------------------
 -- Generic and TH encoding configuration
diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,5 +1,5 @@
 name:            aeson
-version:         1.2.0.0
+version:         1.2.1.0
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Web, JSON
@@ -225,7 +225,7 @@
     unordered-containers,
     uuid-types,
     vector,
-    quickcheck-instances >=0.3.12
+    quickcheck-instances >=0.3.14
 
   if flag(bytestring-builder)
     build-depends: bytestring >= 0.9 && < 0.10.4,
diff --git a/benchmarks/Options.hs b/benchmarks/Options.hs
--- a/benchmarks/Options.hs
+++ b/benchmarks/Options.hs
@@ -1,4 +1,4 @@
-module Options where
+module Options (opts) where
 
 import Prelude ()
 import Prelude.Compat
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,10 +1,18 @@
 For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md).
 
+## 1.2.1.0
+
+* Add `parserThrowError` and `parserCatchError` combinators, thanks to Oleg Grenrus.
+
+* Add `Generic` instance for `Value`, thanks to Xia Li-yao.
+
+* Fix a mistake in the 1.2.0.0 changelog, the `cffi` flag is disabled by default! Thanks to dbaynard.
+
 ## 1.2.0.0
 
 * `tagSingleConstructors`, an option to encode single-constructor types as tagged sums was added to `Options`. It is disabled by default for backward compatibility.
 
-* The `cffi` flag is now turned on by default, this means C FFI code is no longer used by default. You can flip the flag to get C implementation.
+* The `cffi` flag is now turned off (`False`) by default, this means C FFI code is no longer used by default. You can flip the flag to get C implementation.
 
 * The `Options` constructor is no longer exposed to prevent new options from being breaking changes, use `defaultOptions` instead.
 
diff --git a/stack-bench.yaml b/stack-bench.yaml
--- a/stack-bench.yaml
+++ b/stack-bench.yaml
@@ -2,3 +2,5 @@
 packages:
 - '.'
 - benchmarks
+extra-deps:
+- quickcheck-instances-0.3.14
diff --git a/stack-lts6.yaml b/stack-lts6.yaml
--- a/stack-lts6.yaml
+++ b/stack-lts6.yaml
@@ -3,8 +3,13 @@
 - '.'
 - attoparsec-iso8601
 extra-deps:
-- semigroups-0.18.2
 - integer-logarithms-1
+- QuickCheck-2.9.2
+- quickcheck-instances-0.3.14
+- semigroups-0.18.2
+- tagged-0.8.5
+- transformers-compat-0.5.1.4
+flags:
 flags:
   aeson:
     fast: true
diff --git a/stack-lts7.yaml b/stack-lts7.yaml
--- a/stack-lts7.yaml
+++ b/stack-lts7.yaml
@@ -4,6 +4,7 @@
 - attoparsec-iso8601
 extra-deps:
 - integer-logarithms-1
+- quickcheck-instances-0.3.14
 flags:
   aeson:
     fast: true
diff --git a/stack-lts8.yaml b/stack-lts8.yaml
--- a/stack-lts8.yaml
+++ b/stack-lts8.yaml
@@ -2,6 +2,8 @@
 packages:
 - '.'
 - attoparsec-iso8601
+extra-deps:
+- quickcheck-instances-0.3.14
 flags:
   aeson:
     fast: true
diff --git a/stack-nightly.yaml b/stack-nightly.yaml
--- a/stack-nightly.yaml
+++ b/stack-nightly.yaml
@@ -2,6 +2,8 @@
 packages:
 - '.'
 - attoparsec-iso8601
+extra-deps:
+- quickcheck-instances-0.3.14
 flags:
   aeson:
     fast: true
diff --git a/stack-pure-unescape.yaml b/stack-pure-unescape.yaml
--- a/stack-pure-unescape.yaml
+++ b/stack-pure-unescape.yaml
@@ -1,6 +1,8 @@
 resolver: lts-8.1
 packages:
 - '.'
+extra-deps:
+- quickcheck-instances-0.3.14
 flags:
   aeson:
     fast: true
diff --git a/tests/DataFamilies/Encoders.hs b/tests/DataFamilies/Encoders.hs
--- a/tests/DataFamilies/Encoders.hs
+++ b/tests/DataFamilies/Encoders.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE TemplateHaskell #-}
 
-module DataFamilies.Encoders where
+module DataFamilies.Encoders (module DataFamilies.Encoders) where
 
 import Prelude ()
 import Prelude.Compat
diff --git a/tests/DataFamilies/Types.hs b/tests/DataFamilies/Types.hs
--- a/tests/DataFamilies/Types.hs
+++ b/tests/DataFamilies/Types.hs
@@ -8,7 +8,7 @@
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 
-module DataFamilies.Types where
+module DataFamilies.Types (module DataFamilies.Types) where
 
 import Prelude ()
 import Prelude.Compat
diff --git a/tests/Encoders.hs b/tests/Encoders.hs
--- a/tests/Encoders.hs
+++ b/tests/Encoders.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE TemplateHaskell #-}
 
-module Encoders where
+module Encoders (module Encoders) where
 
 import Prelude ()
 import Prelude.Compat
diff --git a/tests/Instances.hs b/tests/Instances.hs
--- a/tests/Instances.hs
+++ b/tests/Instances.hs
@@ -16,7 +16,6 @@
 import Data.Function (on)
 import Data.Functor.Compose (Compose (..))
 import Data.Proxy (Proxy(..))
-import Data.Tagged (Tagged(..))
 import Data.Time (ZonedTime(..), TimeZone(..))
 import Data.Time.Clock (UTCTime(..))
 import Functions
@@ -24,7 +23,6 @@
 import Types
 import qualified Data.DList as DList
 import qualified Data.HashMap.Strict as HM
-import qualified Data.UUID.Types as UUID
 
 #if !MIN_VERSION_QuickCheck(2,9,0)
 import Control.Applicative (Const(..))
@@ -193,9 +191,6 @@
 instance Arbitrary (Proxy a) where
     arbitrary = pure Proxy
 
-instance Arbitrary b => Arbitrary (Tagged a b) where
-    arbitrary = Tagged <$> arbitrary
-
 instance Arbitrary a => Arbitrary (DList.DList a) where
     arbitrary = DList.fromList <$> arbitrary
 
@@ -220,10 +215,3 @@
 instance Arbitrary a => Arbitrary (Identity a) where
     arbitrary = Identity <$> arbitrary
 #endif
-
-instance Arbitrary UUID.UUID where
-    arbitrary = UUID.fromWords
-        <$> arbitrary
-        <*> arbitrary
-        <*> arbitrary
-        <*> arbitrary
diff --git a/tests/Options.hs b/tests/Options.hs
--- a/tests/Options.hs
+++ b/tests/Options.hs
@@ -1,4 +1,4 @@
-module Options where
+module Options (module Options) where
 
 import Prelude ()
 import Prelude.Compat
diff --git a/tests/Properties.hs b/tests/Properties.hs
--- a/tests/Properties.hs
+++ b/tests/Properties.hs
@@ -4,7 +4,7 @@
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
-module Properties where
+module Properties (module Properties) where
 
 import Prelude ()
 import Prelude.Compat
@@ -13,6 +13,7 @@
 import Data.Aeson (eitherDecode, encode)
 import Data.Aeson.Encoding (encodingToLazyByteString)
 import Data.Aeson.Internal (IResult(..), formatError, ifromJSON, iparse)
+import qualified Data.Aeson.Internal as I
 import Data.Aeson.Parser (value)
 import Data.Aeson.Types
 import Data.DList (DList)
@@ -113,6 +114,29 @@
     result :: Result ()
     result = parse parser ()
 
+parserThrowErrorProp :: String -> Property
+parserThrowErrorProp msg =
+    result === Error msg
+  where
+    parser = const $ parserThrowError [] msg
+    result :: Result ()
+    result = parse parser ()
+
+-- | Tests (also) that we catch the JSONPath and it has elements in the right order.
+parserCatchErrorProp :: [String] -> String -> Property
+parserCatchErrorProp path msg =
+    result === Success ([I.Key "outer", I.Key "inner"] ++ jsonPath, msg)
+  where
+    parser = parserCatchError outer (curry pure)
+
+    outer = inner I.<?> I.Key "outer"
+    inner = parserThrowError jsonPath msg I.<?> I.Key "inner"
+
+    result :: Result (I.JSONPath, String)
+    result = parse (const parser) ()
+
+    jsonPath = map (I.Key . T.pack) path
+
 -- | Perform a structural comparison of the results of two encoding
 -- methods. Compares decoded values to account for HashMap-driven
 -- variation in JSON object key ordering.
@@ -306,6 +330,8 @@
     ]
   , testGroup "failure messages" [
       testProperty "modify failure" modifyFailureProp
+    , testProperty "parserThrowError" parserThrowErrorProp
+    , testProperty "parserCatchError" parserCatchErrorProp
     ]
   , testGroup "generic" [
       testGroup "toJSON" [
diff --git a/tests/Types.hs b/tests/Types.hs
--- a/tests/Types.hs
+++ b/tests/Types.hs
@@ -7,7 +7,7 @@
 {-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
-module Types where
+module Types (module Types) where
 
 import Prelude ()
 import Prelude.Compat
