diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Changes in 0.32.0
+  - Support Cabal 3.0
+  - Switch reexported-modules to comma-separated list
+
 ## Changes in 0.31.2
   - Add default value for maintainer (see #339)
   - Escape commas and spaces in filenames when generating cabal files
diff --git a/hpack.cabal b/hpack.cabal
--- a/hpack.cabal
+++ b/hpack.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.31.0.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 3d060180293c32b8d0c25b710d0f419e96a6cc6ec3f95ac5e70bb77f44cbafc3
+-- hash: c5457d3b30dfe5c53d197ff823ed96a5e37e8958aceebdad81606299b87f341d
 
 name:           hpack
-version:        0.31.2
+version:        0.32.0
 synopsis:       A modern format for Haskell packages
 description:    See README at <https://github.com/sol/hpack#readme>
 category:       Development
@@ -31,7 +31,7 @@
   build-depends:
       Cabal >=2.2
     , Glob >=0.9.0
-    , aeson >=1.2.1.0
+    , aeson >=1.4.3.0
     , base >=4.9 && <5
     , bifunctors
     , bytestring
@@ -87,7 +87,7 @@
   build-depends:
       Cabal >=2.2
     , Glob >=0.9.0
-    , aeson >=1.2.1.0
+    , aeson >=1.4.3.0
     , base >=4.9 && <5
     , bifunctors
     , bytestring
@@ -125,7 +125,7 @@
     , Glob >=0.9.0
     , HUnit >=1.6.0.0
     , QuickCheck
-    , aeson >=1.2.1.0
+    , aeson >=1.4.3.0
     , base >=4.9 && <5
     , bifunctors
     , bytestring
diff --git a/src/Hpack/License.hs b/src/Hpack/License.hs
--- a/src/Hpack/License.hs
+++ b/src/Hpack/License.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE ViewPatterns #-}
 {-# LANGUAGE LambdaCase #-}
@@ -9,7 +10,11 @@
 import           Distribution.Version (mkVersion)
 import qualified Distribution.License as Cabal
 import qualified Distribution.SPDX.License as SPDX
+#if MIN_VERSION_Cabal(3,0,0)
+import           Distribution.Parsec (eitherParsec)
+#else
 import           Distribution.Parsec.Class (eitherParsec)
+#endif
 
 import qualified Data.License.Infer as Infer
 
diff --git a/src/Hpack/Render.hs b/src/Hpack/Render.hs
--- a/src/Hpack/Render.hs
+++ b/src/Hpack/Render.hs
@@ -306,7 +306,7 @@
 renderGeneratedModules = Field "autogen-modules" . LineSeparatedList
 
 renderReexportedModules :: [String] -> Element
-renderReexportedModules = Field "reexported-modules" . LineSeparatedList
+renderReexportedModules = Field "reexported-modules" . CommaSeparatedList
 
 renderSignatures :: [String] -> Element
 renderSignatures = Field "signatures" . CommaSeparatedList
diff --git a/src/Hpack/Syntax/DependencyVersion.hs b/src/Hpack/Syntax/DependencyVersion.hs
--- a/src/Hpack/Syntax/DependencyVersion.hs
+++ b/src/Hpack/Syntax/DependencyVersion.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE LambdaCase #-}
 module Hpack.Syntax.DependencyVersion (
@@ -32,9 +33,15 @@
 import           Text.PrettyPrint (renderStyle, Style(..), Mode(..))
 
 import           Distribution.Version (VersionRangeF(..))
-import qualified Distribution.Text as D
 import qualified Distribution.Version as D
+
+#if MIN_VERSION_Cabal(3,0,0)
+import qualified Distribution.Parsec as D
+import qualified Distribution.Pretty as D
+#else
 import qualified Distribution.Parsec.Class as D
+import qualified Distribution.Text as D
+#endif
 
 import           Data.Aeson.Config.FromValue
 
@@ -147,7 +154,13 @@
 versionConstraintFromCabal :: D.VersionRange -> VersionConstraint
 versionConstraintFromCabal range
   | D.isAnyVersion range = AnyVersion
-  | otherwise = VersionRange . renderStyle style . D.disp $ toPreCabal2VersionRange range
+  | otherwise = VersionRange . renderStyle style .
+#if MIN_VERSION_Cabal(3,0,0)
+      D.pretty
+#else
+      D.disp
+#endif
+      $ toPreCabal2VersionRange range
   where
     style = Style OneLineMode 0 0
 
diff --git a/test/Data/Aeson/Config/FromValueSpec.hs b/test/Data/Aeson/Config/FromValueSpec.hs
--- a/test/Data/Aeson/Config/FromValueSpec.hs
+++ b/test/Data/Aeson/Config/FromValueSpec.hs
@@ -85,7 +85,7 @@
         [yaml|
         name: "Joe"
         age: "23"
-        |] `shouldDecodeTo` left "Error while parsing $.age - expected Int, encountered String"
+        |] `shouldDecodeTo` left "Error while parsing $.age - parsing Int failed, expected Number, but encountered String"
 
     context "with (,)" $ do
       it "captures unrecognized fields" $ do
diff --git a/test/Data/Aeson/Config/TypesSpec.hs b/test/Data/Aeson/Config/TypesSpec.hs
--- a/test/Data/Aeson/Config/TypesSpec.hs
+++ b/test/Data/Aeson/Config/TypesSpec.hs
@@ -13,7 +13,7 @@
     context "List" $ do
       let
         parseError :: String -> Result (List Int)
-        parseError prefix = Left (prefix ++ " - expected Int, encountered String")
+        parseError prefix = Left (prefix ++ " - parsing Int failed, expected Number, but encountered String")
 
       context "when parsing single values" $ do
         it "returns the value in a singleton list" $ do
diff --git a/test/EndToEndSpec.hs b/test/EndToEndSpec.hs
--- a/test/EndToEndSpec.hs
+++ b/test/EndToEndSpec.hs
@@ -285,7 +285,7 @@
           path: defaults.yaml
           ref: "2017"
         library: {}
-        |] `shouldFailWith` (file ++ ": Error while parsing $ - expected Object, encountered Array")
+        |] `shouldFailWith` (file ++ ": Error while parsing $ - expected Object, but encountered Array")
 
       it "warns on unknown fields" $ do
         let file = joinPath ["defaults", "sol", "hpack-template", "2017", "defaults.yaml"]
@@ -340,7 +340,7 @@
       it "rejects other values" $ do
         [i|
         version: {}
-        |] `shouldFailWith` "package.yaml: Error while parsing $.version - expected Number or String, encountered Object"
+        |] `shouldFailWith` "package.yaml: Error while parsing $.version - expected Number or String, but encountered Object"
 
     describe "license" $ do
       it "accepts cabal-style licenses" $ do
@@ -1363,14 +1363,14 @@
             then:
               dependencies: Win32
             else: null
-          |] `shouldFailWith` "package.yaml: Error while parsing $.when.else - expected Object, encountered Null"
+          |] `shouldFailWith` "package.yaml: Error while parsing $.when.else - expected Object, but encountered Null"
 
         it "rejects invalid conditionals" $ do
           [i|
             dependencies:
               - foo
               - 23
-          |] `shouldFailWith` "package.yaml: Error while parsing $.dependencies[1] - expected Object or String, encountered Number"
+          |] `shouldFailWith` "package.yaml: Error while parsing $.dependencies[1] - expected Object or String, but encountered Number"
 
         it "warns on unknown fields" $ do
           [i|
diff --git a/test/Hpack/ConfigSpec.hs b/test/Hpack/ConfigSpec.hs
--- a/test/Hpack/ConfigSpec.hs
+++ b/test/Hpack/ConfigSpec.hs
@@ -675,7 +675,7 @@
       it "rejects other values" $ do
         [yaml|
         23
-        |] `shouldDecodeTo` (Left "Error while parsing $ - expected Boolean or String, encountered Number" :: Result Cond)
+        |] `shouldDecodeTo` (Left "Error while parsing $ - expected Boolean or String, but encountered Number" :: Result Cond)
 
   describe "formatOrList" $ do
     it "formats a singleton list" $ do
diff --git a/test/Hpack/LicenseSpec.hs b/test/Hpack/LicenseSpec.hs
--- a/test/Hpack/LicenseSpec.hs
+++ b/test/Hpack/LicenseSpec.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE QuasiQuotes #-}
 module Hpack.LicenseSpec (spec) where
 
@@ -6,7 +7,11 @@
 import           Data.String.Interpolate
 
 import           Distribution.Pretty (prettyShow)
+#if MIN_VERSION_Cabal(3,0,0)
+import           Distribution.Parsec (simpleParsec)
+#else
 import           Distribution.Parsec.Class (simpleParsec)
+#endif
 import qualified Distribution.License as Cabal
 
 import           Hpack.License
diff --git a/test/Hpack/Syntax/DefaultsSpec.hs b/test/Hpack/Syntax/DefaultsSpec.hs
--- a/test/Hpack/Syntax/DefaultsSpec.hs
+++ b/test/Hpack/Syntax/DefaultsSpec.hs
@@ -151,4 +151,4 @@
         it "fails" $ do
           [yaml|
           10
-          |] `shouldDecodeTo` left "Error while parsing $ - expected Object or String, encountered Number"
+          |] `shouldDecodeTo` left "Error while parsing $ - expected Object or String, but encountered Number"
diff --git a/test/Hpack/Syntax/DependenciesSpec.hs b/test/Hpack/Syntax/DependenciesSpec.hs
--- a/test/Hpack/Syntax/DependenciesSpec.hs
+++ b/test/Hpack/Syntax/DependenciesSpec.hs
@@ -125,7 +125,7 @@
         it "rejects invalid values" $ do
           [yaml|
             hpack: []
-          |] `shouldDecodeTo` left "Error while parsing $.hpack - expected Null, Object, Number, or String, encountered Array"
+          |] `shouldDecodeTo` left "Error while parsing $.hpack - expected Null, Object, Number, or String, but encountered Array"
 
         context "when the constraint is a Number" $ do
           it "accepts 1" $ do
@@ -213,7 +213,7 @@
               [yaml|
                 foo:
                   version: {}
-              |] `shouldDecodeTo` left "Error while parsing $.foo.version - expected Null, Number, or String, encountered Object"
+              |] `shouldDecodeTo` left "Error while parsing $.foo.version - expected Null, Number, or String, but encountered Object"
 
             it "accepts a string" $ do
               [yaml|
