diff --git a/Statistics/Distribution/Beta.hs b/Statistics/Distribution/Beta.hs
--- a/Statistics/Distribution/Beta.hs
+++ b/Statistics/Distribution/Beta.hs
@@ -20,6 +20,7 @@
   , bdBeta
   ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -37,6 +38,9 @@
  , bdBeta  :: {-# UNPACK #-} !Double
    -- ^ Beta shape parameter
  } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON BetaDistribution
+instance ToJSON BetaDistribution
 
 instance Binary BetaDistribution where
     put (BD x y) = put x >> put y
diff --git a/Statistics/Distribution/Binomial.hs b/Statistics/Distribution/Binomial.hs
--- a/Statistics/Distribution/Binomial.hs
+++ b/Statistics/Distribution/Binomial.hs
@@ -23,6 +23,7 @@
     , bdProbability
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -41,6 +42,9 @@
     , bdProbability :: {-# UNPACK #-} !Double
     -- ^ Probability.
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON BinomialDistribution
+instance ToJSON BinomialDistribution
 
 instance Binary BinomialDistribution where
     put (BD x y) = put x >> put y
diff --git a/Statistics/Distribution/CauchyLorentz.hs b/Statistics/Distribution/CauchyLorentz.hs
--- a/Statistics/Distribution/CauchyLorentz.hs
+++ b/Statistics/Distribution/CauchyLorentz.hs
@@ -21,6 +21,7 @@
   , standardCauchy
   ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -40,6 +41,9 @@
   , cauchyDistribScale  :: {-# UNPACK #-} !Double
   }
   deriving (Eq, Show, Read, Typeable, Data, Generic)
+
+instance FromJSON CauchyDistribution
+instance ToJSON CauchyDistribution
 
 instance Binary CauchyDistribution where
     put (CD x y) = put x >> put y
diff --git a/Statistics/Distribution/ChiSquared.hs b/Statistics/Distribution/ChiSquared.hs
--- a/Statistics/Distribution/ChiSquared.hs
+++ b/Statistics/Distribution/ChiSquared.hs
@@ -18,6 +18,7 @@
         , chiSquaredNDF
         ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -32,6 +33,9 @@
 -- | Chi-squared distribution
 newtype ChiSquared = ChiSquared Int
                      deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON ChiSquared
+instance ToJSON ChiSquared
 
 instance Binary ChiSquared where
     get = fmap ChiSquared get
diff --git a/Statistics/Distribution/Exponential.hs b/Statistics/Distribution/Exponential.hs
--- a/Statistics/Distribution/Exponential.hs
+++ b/Statistics/Distribution/Exponential.hs
@@ -23,6 +23,7 @@
     , edLambda
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -37,6 +38,9 @@
 newtype ExponentialDistribution = ED {
       edLambda :: Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON ExponentialDistribution
+instance ToJSON ExponentialDistribution
 
 instance Binary ExponentialDistribution where
     put = put . edLambda
diff --git a/Statistics/Distribution/FDistribution.hs b/Statistics/Distribution/FDistribution.hs
--- a/Statistics/Distribution/FDistribution.hs
+++ b/Statistics/Distribution/FDistribution.hs
@@ -16,6 +16,7 @@
   , fDistributionNDF2
   ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import Numeric.MathFunctions.Constants (m_neg_inf)
@@ -27,14 +28,15 @@
 import Data.Binary (put, get)
 import Control.Applicative ((<$>), (<*>))
 
-
-
 -- | F distribution
 data FDistribution = F { fDistributionNDF1 :: {-# UNPACK #-} !Double
                        , fDistributionNDF2 :: {-# UNPACK #-} !Double
                        , _pdfFactor        :: {-# UNPACK #-} !Double
                        }
                    deriving (Eq, Show, Read, Typeable, Data, Generic)
+
+instance FromJSON FDistribution
+instance ToJSON FDistribution
 
 instance Binary FDistribution where
     get = F <$> get <*> get <*> get
diff --git a/Statistics/Distribution/Gamma.hs b/Statistics/Distribution/Gamma.hs
--- a/Statistics/Distribution/Gamma.hs
+++ b/Statistics/Distribution/Gamma.hs
@@ -25,6 +25,7 @@
     , gdScale
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Applicative ((<$>), (<*>))
 import Data.Binary (Binary)
 import Data.Binary (put, get)
@@ -41,6 +42,9 @@
       gdShape :: {-# UNPACK #-} !Double -- ^ Shape parameter, /k/.
     , gdScale :: {-# UNPACK #-} !Double -- ^ Scale parameter, &#977;.
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON GammaDistribution
+instance ToJSON GammaDistribution
 
 instance Binary GammaDistribution where
     put (GD x y) = put x >> put y
diff --git a/Statistics/Distribution/Geometric.hs b/Statistics/Distribution/Geometric.hs
--- a/Statistics/Distribution/Geometric.hs
+++ b/Statistics/Distribution/Geometric.hs
@@ -30,6 +30,7 @@
     , gdSuccess0
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Applicative ((<$>))
 import Control.Monad (liftM)
 import Data.Binary (Binary)
@@ -47,6 +48,9 @@
       gdSuccess :: Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
 
+instance FromJSON GeometricDistribution
+instance ToJSON GeometricDistribution
+
 instance Binary GeometricDistribution where
     get = GD <$> get
     put (GD x) = put x
@@ -113,6 +117,9 @@
 newtype GeometricDistribution0 = GD0 {
       gdSuccess0 :: Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON GeometricDistribution0
+instance ToJSON GeometricDistribution0
 
 instance Binary GeometricDistribution0 where
     get = GD0 <$> get
diff --git a/Statistics/Distribution/Hypergeometric.hs b/Statistics/Distribution/Hypergeometric.hs
--- a/Statistics/Distribution/Hypergeometric.hs
+++ b/Statistics/Distribution/Hypergeometric.hs
@@ -27,6 +27,7 @@
     , hdK
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -41,6 +42,9 @@
     , hdL :: {-# UNPACK #-} !Int
     , hdK :: {-# UNPACK #-} !Int
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON HypergeometricDistribution
+instance ToJSON HypergeometricDistribution
 
 instance Binary HypergeometricDistribution where
     get = HD <$> get <*> get <*> get
diff --git a/Statistics/Distribution/Normal.hs b/Statistics/Distribution/Normal.hs
--- a/Statistics/Distribution/Normal.hs
+++ b/Statistics/Distribution/Normal.hs
@@ -20,6 +20,7 @@
     , standard
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Applicative ((<$>), (<*>))
 import Data.Binary (Binary)
 import Data.Binary (put, get)
@@ -31,7 +32,6 @@
 import qualified Statistics.Sample as S
 import qualified System.Random.MWC.Distributions as MWC
 
-
 -- | The normal distribution.
 data NormalDistribution = ND {
       mean       :: {-# UNPACK #-} !Double
@@ -39,6 +39,9 @@
     , ndPdfDenom :: {-# UNPACK #-} !Double
     , ndCdfDenom :: {-# UNPACK #-} !Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON NormalDistribution
+instance ToJSON NormalDistribution
 
 instance Binary NormalDistribution where
     put (ND w x y z) = put w >> put x >> put y >> put z
diff --git a/Statistics/Distribution/Poisson.hs b/Statistics/Distribution/Poisson.hs
--- a/Statistics/Distribution/Poisson.hs
+++ b/Statistics/Distribution/Poisson.hs
@@ -24,6 +24,7 @@
     -- $references
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -37,6 +38,9 @@
 newtype PoissonDistribution = PD {
       poissonLambda :: Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON PoissonDistribution
+instance ToJSON PoissonDistribution
 
 instance Binary PoissonDistribution where
     get = fmap PD get
diff --git a/Statistics/Distribution/StudentT.hs b/Statistics/Distribution/StudentT.hs
--- a/Statistics/Distribution/StudentT.hs
+++ b/Statistics/Distribution/StudentT.hs
@@ -16,6 +16,7 @@
   , studentTUnstandardized
   ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -28,6 +29,9 @@
 -- | Student-T distribution
 newtype StudentT = StudentT { studentTndf :: Double }
                    deriving (Eq, Show, Read, Typeable, Data, Generic)
+
+instance FromJSON StudentT
+instance ToJSON StudentT
 
 instance Binary StudentT where
     put = put . studentTndf
diff --git a/Statistics/Distribution/Transform.hs b/Statistics/Distribution/Transform.hs
--- a/Statistics/Distribution/Transform.hs
+++ b/Statistics/Distribution/Transform.hs
@@ -17,6 +17,7 @@
     , scaleAround
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Applicative ((<*>))
 import Data.Binary (Binary)
 import Data.Binary (put, get)
@@ -37,6 +38,9 @@
   , linTransDistr    :: d
     -- ^ Distribution being transformed.
   } deriving (Eq, Show, Read, Typeable, Data, Generic)
+
+instance (FromJSON d) => FromJSON (LinearTransform d)
+instance (ToJSON d) => ToJSON (LinearTransform d)
 
 instance (Binary d) => Binary (LinearTransform d) where
     get = LinearTransform <$> get <*> get <*> get
diff --git a/Statistics/Distribution/Uniform.hs b/Statistics/Distribution/Uniform.hs
--- a/Statistics/Distribution/Uniform.hs
+++ b/Statistics/Distribution/Uniform.hs
@@ -19,6 +19,7 @@
     , uniformB
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Data (Data, Typeable)
 import GHC.Generics (Generic)
@@ -33,6 +34,9 @@
       uniformA :: {-# UNPACK #-} !Double -- ^ Low boundary of distribution
     , uniformB :: {-# UNPACK #-} !Double -- ^ Upper boundary of distribution
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON UniformDistribution
+instance ToJSON UniformDistribution
 
 instance Binary UniformDistribution where
     put (UniformDistribution x y) = put x >> put y
diff --git a/Statistics/Math/RootFinding.hs b/Statistics/Math/RootFinding.hs
--- a/Statistics/Math/RootFinding.hs
+++ b/Statistics/Math/RootFinding.hs
@@ -20,6 +20,7 @@
     -- $references
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Applicative (Alternative(..), Applicative(..))
 import Control.Monad (MonadPlus(..), ap)
 import Data.Binary (Binary)
@@ -41,6 +42,9 @@
             | Root a
             -- ^ A root was successfully found.
               deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance (FromJSON a) => FromJSON (Root a)
+instance (ToJSON a) => ToJSON (Root a)
 
 instance (Binary a) => Binary (Root a) where
     put NotBracketed = putWord8 0
diff --git a/Statistics/Regression.hs b/Statistics/Regression.hs
--- a/Statistics/Regression.hs
+++ b/Statistics/Regression.hs
@@ -7,19 +7,54 @@
 
 module Statistics.Regression
     (
-      ols
+      olsRegress
+    , ols
     , rSquare
     ) where
 
 import Control.Applicative ((<$>))
-import Prelude hiding (sum)
+import Prelude hiding (pred, sum)
 import Statistics.Function as F
-import Statistics.Matrix
+import Statistics.Matrix hiding (map)
 import Statistics.Matrix.Algorithms (qr)
 import Statistics.Sample (mean)
 import Statistics.Sample.Internal (sum)
+import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Unboxed as U
 import qualified Data.Vector.Unboxed.Mutable as M
+
+-- | Perform an ordinary least-squares regression on a set of
+-- predictors, and calculate the goodness-of-fit of the regression.
+--
+-- The returned pair consists of:
+--
+-- * A vector of regression coefficients.  This vector has /one more/
+--   element than the list of predictors; the last element is the
+--   /y/-intercept value.
+--
+-- * /R&#0178;/, the coefficient of determination (see 'rSquare' for
+--   details).
+olsRegress :: [Vector]
+              -- ^ Non-empty list of predictor vectors.  Must all have
+              -- the same length.  These will become the columns of
+              -- the matrix /A/ solved by 'ols'.
+           -> Vector
+              -- ^ Responder vector.  Must have the same length as the
+              -- predictor vectors.
+           -> (Vector, Double)
+olsRegress preds@(_:_) resps
+  | any (/=n) ls        = error $ "predictor vector length mismatch " ++
+                                  show lss
+  | G.length resps /= n = error $ "responder/predictor length mismatch " ++
+                                  show (G.length resps, n)
+  | otherwise           = (coeffs, rSquare mxpreds resps coeffs)
+  where
+    coeffs    = ols mxpreds resps
+    mxpreds   = transpose .
+                fromVector (length lss + 1) n .
+                G.concat $ preds ++ [G.replicate n 1]
+    lss@(n:ls) = map G.length preds
+olsRegress _ _ = error "no predictors given"
 
 -- | Compute the ordinary least-squares solution to /A x = b/.
 ols :: Matrix     -- ^ /A/ has at least as many rows as columns.
diff --git a/Statistics/Resampling.hs b/Statistics/Resampling.hs
--- a/Statistics/Resampling.hs
+++ b/Statistics/Resampling.hs
@@ -23,6 +23,7 @@
     , estimate
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Control.Concurrent (forkIO, newChan, readChan, writeChan)
 import Control.Monad (forM_, liftM, replicateM_)
 import Control.Monad.Primitive (PrimState)
@@ -49,6 +50,9 @@
 newtype Resample = Resample {
       fromResample :: U.Vector Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON Resample
+instance ToJSON Resample
 
 instance Binary Resample where
     put = put . fromResample
diff --git a/Statistics/Resampling/Bootstrap.hs b/Statistics/Resampling/Bootstrap.hs
--- a/Statistics/Resampling/Bootstrap.hs
+++ b/Statistics/Resampling/Bootstrap.hs
@@ -25,6 +25,7 @@
 import Control.DeepSeq (NFData)
 import Control.Exception (assert)
 import Control.Monad.Par (parMap, runPar)
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary)
 import Data.Binary (put, get)
 import Data.Data (Data)
@@ -52,6 +53,9 @@
     , estConfidenceLevel :: {-# UNPACK #-} !Double
     -- ^ Confidence level of the confidence intervals.
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON Estimate
+instance ToJSON Estimate
 
 instance Binary Estimate where
     put (Estimate w x y z) = put w >> put x >> put y >> put z
diff --git a/Statistics/Sample/KernelDensity/Simple.hs b/Statistics/Sample/KernelDensity/Simple.hs
--- a/Statistics/Sample/KernelDensity/Simple.hs
+++ b/Statistics/Sample/KernelDensity/Simple.hs
@@ -46,6 +46,7 @@
     -- $references
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary(..))
 import Data.Data (Data, Typeable)
 import Data.Vector.Binary ()
@@ -62,6 +63,9 @@
 newtype Points = Points {
       fromPoints :: U.Vector Double
     } deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON Points
+instance ToJSON Points
 
 instance Binary Points where
     get = fmap Points get
diff --git a/Statistics/Sample/Powers.hs b/Statistics/Sample/Powers.hs
--- a/Statistics/Sample/Powers.hs
+++ b/Statistics/Sample/Powers.hs
@@ -47,6 +47,7 @@
     -- $references
     ) where
 
+import Data.Aeson (FromJSON, ToJSON)
 import Data.Binary (Binary(..))
 import Data.Data (Data, Typeable)
 import Data.Vector.Binary ()
@@ -66,6 +67,9 @@
 
 newtype Powers = Powers (U.Vector Double)
     deriving (Eq, Read, Show, Typeable, Data, Generic)
+
+instance FromJSON Powers
+instance ToJSON Powers
 
 instance Binary Powers where
     put (Powers v) = put v
diff --git a/Statistics/Test/Types.hs b/Statistics/Test/Types.hs
--- a/Statistics/Test/Types.hs
+++ b/Statistics/Test/Types.hs
@@ -1,11 +1,13 @@
-{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
 module Statistics.Test.Types (
     TestType(..)
   , TestResult(..)
   , significant
   ) where
 
-import Data.Typeable (Typeable)
+import Data.Aeson (FromJSON, ToJSON)
+import Data.Data (Typeable, Data)
+import GHC.Generics
 
 
 -- | Test type. Exact meaning depends on a specific test. But
@@ -13,12 +15,18 @@
 -- for 'OneTailed' or whether it too big or too small for 'TwoTailed'
 data TestType = OneTailed
               | TwoTailed
-              deriving (Eq,Ord,Show,Typeable)
+              deriving (Eq,Ord,Show,Typeable,Data,Generic)
 
+instance FromJSON TestType
+instance ToJSON TestType
+
 -- | Result of hypothesis testing
 data TestResult = Significant    -- ^ Null hypothesis should be rejected
                 | NotSignificant -- ^ Data is compatible with hypothesis
-                  deriving (Eq,Ord,Show,Typeable)
+                  deriving (Eq,Ord,Show,Typeable,Data,Generic)
+
+instance FromJSON TestResult
+instance ToJSON TestResult
 
 -- | Significant if parameter is 'True', not significant otherwiser
 significant :: Bool -> TestResult
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+Changes in 0.13.0.0
+
+  * All types now support JSON encoding and decoding.
+
 Changes in 0.12.0.0
 
   * The `Statistics.Math` module has been removed, after being
diff --git a/statistics.cabal b/statistics.cabal
--- a/statistics.cabal
+++ b/statistics.cabal
@@ -1,5 +1,5 @@
 name:           statistics
-version:        0.12.0.0
+version:        0.13.1.0
 synopsis:       A library of statistical types, data, and functions
 description:
   This library provides a number of common functions and types useful
@@ -95,6 +95,7 @@
     Statistics.Sample.Internal
     Statistics.Test.Internal
   build-depends:
+    aeson >= 0.6.0.0,
     base >= 4.4 && < 5,
     binary >= 0.5.1.0,
     deepseq >= 1.1.0.2,
