diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Andrew Martin (c) 2016
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Andrew Martin nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/quantification-aeson.cabal b/quantification-aeson.cabal
new file mode 100644
--- /dev/null
+++ b/quantification-aeson.cabal
@@ -0,0 +1,31 @@
+cabal-version: 2.4
+name: quantification-aeson
+version: 0.8
+synopsis: Rage against the quantification - integration with Aeson
+description: Data types and typeclasses to deal with universally and existentially quantified types
+homepage: https://github.com/andrewthad/quantification#readme
+license: BSD-3-Clause
+license-file: LICENSE
+author: Andrew Martin, Marseille Bouchard
+maintainer: andrew.thaddeus@gmail.com
+copyright: 2018 Andrew Martin
+category: Web
+build-type: Simple
+
+library
+  hs-source-dirs: src
+  exposed-modules:
+    Data.Exists.Aeson
+  build-depends:
+    , aeson >= 2.2 && < 2.3
+    , base >= 4.11.1 && < 5
+    , containers >= 0.5 && < 0.7
+    , quantification >=0.8 && <0.9
+    , unordered-containers >= 0.2 && < 0.3
+    , vector >= 0.11 && < 0.14
+  default-language: Haskell2010
+  ghc-options: -O2 -Wall
+
+source-repository head
+  type:     git
+  location: https://github.com/andrewthad/quantification
diff --git a/src/Data/Exists/Aeson.hs b/src/Data/Exists/Aeson.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Exists/Aeson.hs
@@ -0,0 +1,250 @@
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Data.Exists.Aeson
+  ( FromJSONForall(..)
+  , FromJSONForeach(..)
+  , FromJSONExists(..)
+  , ToJSONForall(..)
+  , ToJSONForeach(..)
+  , ToJSONKeyFunctionForall(..)
+  , FromJSONKeyFunctionForeach(..)
+  , ToJSONKeyForall(..)
+  , ToJSONKeyForeach(..)
+  , FromJSONKeyExists(..)
+  , FromJSONKeyForeach(..)
+  , ToJSONSing(..)
+  , FromJSONSing(..)
+  , parseJSONMapForeachKey
+  , toJSONMapForeachKey
+  ) where
+
+import Control.Applicative (Const(..))
+import Data.Aeson ((<?>))
+import Data.Aeson (ToJSON(..),FromJSON(..))
+import Data.Aeson (ToJSONKey(..),FromJSONKey(..))
+import Data.Aeson (ToJSONKeyFunction(..),FromJSONKeyFunction(..))
+import Data.Aeson.Types (JSONPathElement(Key,Index))
+import Data.Coerce (coerce)
+import Data.Exists (Exists(..),Some(..),Sing,ApplyForeach(..),OrdForeach)
+import Data.Exists (Reify(..),Unreify(..))
+import Data.Functor.Compose (Compose(..))
+import Data.Functor.Product (Product(..))
+import Data.Kind (Type)
+import Data.Map.Strict (Map)
+
+import qualified Data.Aeson.Encoding as Aeson
+import qualified Data.Aeson.Encoding.Internal as AEI
+import qualified Data.Aeson.Key as Key
+import qualified Data.Aeson.KeyMap as KM
+import qualified Data.Aeson.Types as Aeson
+import qualified Data.HashMap.Strict as HM
+import qualified Data.Map.Strict as M
+import qualified Data.Traversable as TRV
+import qualified Data.Vector as V
+
+data ToJSONKeyFunctionForall f
+  = ToJSONKeyTextForall !(forall a. f a -> Aeson.Key) !(forall a. f a -> Aeson.Encoding' Aeson.Key)
+  | ToJSONKeyValueForall !(forall a. f a -> Aeson.Value) !(forall a. f a -> Aeson.Encoding)
+data FromJSONKeyFunctionForeach f
+  = FromJSONKeyTextParserForeach !(forall a. Sing a -> Aeson.Key -> Aeson.Parser (f a))
+  | FromJSONKeyValueForeach !(forall a. Sing a -> Aeson.Value -> Aeson.Parser (f a))
+
+instance (ToJSONForeach f, Reify a) => ToJSON (ApplyForeach f a) where
+  toJSON = toJSONForeach reify
+
+instance (FromJSONForeach f, Reify a) => FromJSON (ApplyForeach f a) where
+  parseJSON = parseJSONForeach reify
+
+instance ToJSONForeach f => ToJSONForeach (ApplyForeach f) where
+  toJSONForeach s (ApplyForeach x) = toJSONForeach s x
+
+instance FromJSONForeach f => FromJSONForeach (ApplyForeach f) where
+  parseJSONForeach s = fmap ApplyForeach . parseJSONForeach s
+
+instance ToJSONKeyForeach f => ToJSONKeyForeach (ApplyForeach f) where
+  toJSONKeyForeach = case toJSONKeyForeach of
+    ToJSONKeyTextForall f g -> ToJSONKeyTextForall
+      (\(Pair s (ApplyForeach x)) -> f (Pair s x))
+      (\(Pair s (ApplyForeach x)) -> g (Pair s x))
+    ToJSONKeyValueForall f g -> ToJSONKeyValueForall
+      (\(Pair s (ApplyForeach x)) -> f (Pair s x))
+      (\(Pair s (ApplyForeach x)) -> g (Pair s x))
+
+instance FromJSONKeyForeach f => FromJSONKeyForeach (ApplyForeach f) where
+  fromJSONKeyForeach = case fromJSONKeyForeach of
+    FromJSONKeyTextParserForeach f -> FromJSONKeyTextParserForeach (\s t -> fmap ApplyForeach (f s t))
+    FromJSONKeyValueForeach f -> FromJSONKeyValueForeach (\s t -> fmap ApplyForeach (f s t))
+
+instance (ToJSONKeyForeach f, Reify a) => ToJSONKey (ApplyForeach f a) where
+  toJSONKey = case toJSONKeyForeach of
+    ToJSONKeyTextForall toText toEnc -> ToJSONKeyText
+      (\(ApplyForeach x) -> toText (Pair reify x))
+      (\(ApplyForeach x) -> toEnc (Pair reify x))
+    ToJSONKeyValueForall toValue toEnc -> ToJSONKeyValue
+      (\(ApplyForeach x) -> toValue (Pair reify x))
+      (\(ApplyForeach x) -> toEnc (Pair reify x))
+  toJSONKeyList = case toJSONKeyForeach of
+    ToJSONKeyTextForall toText toEnc -> ToJSONKeyValue
+      (\xs -> toJSON $ map (\(ApplyForeach x) -> toText (Pair reify x)) xs)
+      (\xs -> Aeson.list (textEncodingToValueEncoding . toEnc . Pair reify) (map getApplyForeach xs))
+    ToJSONKeyValueForall toValue toEnc -> ToJSONKeyValue
+      (\xs -> toJSON $ map (\(ApplyForeach x) -> toValue (Pair reify x)) xs)
+      (\xs -> Aeson.list (toEnc . Pair reify) (map getApplyForeach xs))
+
+-- this is always safe
+textEncodingToValueEncoding :: Aeson.Encoding' Aeson.Key -> Aeson.Encoding' Aeson.Value
+textEncodingToValueEncoding = AEI.retagEncoding
+
+instance (FromJSONKeyForeach f, Reify a) => FromJSONKey (ApplyForeach f a) where
+  fromJSONKey = case fromJSONKeyForeach of
+    FromJSONKeyTextParserForeach f -> FromJSONKeyTextParser (fmap ApplyForeach . f reify . Key.fromText)
+    FromJSONKeyValueForeach f -> FromJSONKeyValue (fmap ApplyForeach . f reify)
+  fromJSONKeyList = case fromJSONKeyForeach of
+    FromJSONKeyTextParserForeach f -> FromJSONKeyValue $ Aeson.withArray "ApplyForeach" $ \xs -> do
+      fmap V.toList (mapM (fmap ApplyForeach . Aeson.withText "ApplyForeach" (f reify . Key.fromText)) xs)
+    FromJSONKeyValueForeach f -> FromJSONKeyValue $ Aeson.withArray "ApplyForeach" $ \xs -> do
+      fmap V.toList (mapM (fmap ApplyForeach . f reify) xs)
+
+class ToJSONKeyForall f where
+  toJSONKeyForall :: ToJSONKeyFunctionForall f
+
+class ToJSONKeyForeach f where
+  toJSONKeyForeach :: ToJSONKeyFunctionForall (Product Sing f)
+
+class FromJSONKeyExists f where
+  fromJSONKeyExists :: FromJSONKeyFunction (Exists f)
+
+class FromJSONKeyForeach f where
+  fromJSONKeyForeach :: FromJSONKeyFunctionForeach f
+
+class ToJSONForall f where
+  toJSONForall :: f a -> Aeson.Value
+
+class ToJSONForeach f where
+  toJSONForeach :: Sing a -> f a -> Aeson.Value
+
+class FromJSONForall f where
+  parseJSONForall :: Sing a -> Aeson.Value -> Aeson.Parser (f a)
+
+class FromJSONForeach f where
+  parseJSONForeach :: Sing a -> Aeson.Value -> Aeson.Parser (f a)
+
+class FromJSONExists f where
+  parseJSONExists :: Aeson.Value -> Aeson.Parser (Exists f)
+
+instance FromJSON a => FromJSONForeach (Const a) where
+  parseJSONForeach _ = fmap Const . parseJSON
+
+instance ToJSON a => ToJSONForeach (Const a) where
+  toJSONForeach _ = coerce (toJSON @a)
+
+-- I need to get rid of the ToJSONForall and FromJSONForeach constraints
+-- on these two instances.
+instance (ToJSONKeyForall f, ToJSONForall f) => ToJSONKey (Exists f) where
+  toJSONKey = case toJSONKeyForall of
+    ToJSONKeyTextForall t e -> ToJSONKeyText (\(Exists a) -> t a) (\(Exists a) -> e a)
+    ToJSONKeyValueForall v e -> ToJSONKeyValue (\x -> case x of Exists a -> v a) (\(Exists a) -> e a)
+
+instance (FromJSONKeyExists f, FromJSONExists f) => FromJSONKey (Exists f) where
+  fromJSONKey = fromJSONKeyExists
+
+instance ToJSONForall f => ToJSON (Exists f) where
+  toJSON (Exists a) = toJSONForall a
+
+instance FromJSONExists f => FromJSON (Exists f) where
+  parseJSON v = parseJSONExists v
+
+instance (Aeson.ToJSON1 f, ToJSONForall g) => ToJSONForall (Compose f g) where
+  toJSONForall (Compose x) = Aeson.liftToJSON (\_ -> False) toJSONForall (Aeson.toJSON . map toJSONForall) x
+
+instance (Aeson.ToJSON1 f, ToJSONForeach g) => ToJSONForeach (Compose f g) where
+  toJSONForeach s (Compose x) = Aeson.liftToJSON (\_ -> False) (toJSONForeach s) (Aeson.toJSON . map (toJSONForeach s)) x
+
+instance (Aeson.FromJSON1 f, FromJSONForeach g) => FromJSONForeach (Compose f g) where
+  parseJSONForeach s = fmap Compose . Aeson.liftParseJSON Nothing
+    (parseJSONForeach s)
+    (Aeson.withArray "Compose" (fmap V.toList . V.mapM (parseJSONForeach s)))
+
+class ToJSONSing k where
+  toJSONSing :: forall (a :: k). Sing a -> Aeson.Value
+
+instance (ToJSONForeach f, ToJSONSing k) => ToJSON (Some (f :: k -> Type)) where
+  toJSON (Some s v) = toJSON [toJSONSing s, toJSONForeach s v]
+
+class FromJSONSing k where
+  parseJSONSing :: Aeson.Value -> Aeson.Parser (Exists (Sing :: k -> Type))
+
+instance (Aeson.FromJSON1 f, FromJSONForall g) => FromJSONForall (Compose f g) where
+  parseJSONForall s = fmap Compose . Aeson.liftParseJSON Nothing
+      (parseJSONForall s)
+          (Aeson.withArray "Compose" (fmap V.toList . V.mapM (parseJSONForall s)))
+
+instance (FromJSONForeach f, FromJSONSing k) => FromJSON (Some (f :: k -> Type)) where
+  parseJSON = Aeson.withArray "Some" $ \v -> if V.length v == 2
+    then do
+      let x = V.unsafeIndex v 0
+          y = V.unsafeIndex v 1
+      Exists s <- parseJSONSing x :: Aeson.Parser (Exists (Sing :: k -> Type))
+      val <- parseJSONForeach s y
+      return (Some s val)
+    else fail "array of length 2 expected"
+
+-- This name is not great. I need to figure out a better naming
+-- scheme that allows this area to grow.
+toJSONMapForeachKey :: (ToJSONKeyForeach f, ToJSONForeach v)
+  => Sing a
+  -> Map (f a) (v a)
+  -> Aeson.Value
+toJSONMapForeachKey s m = case toJSONKeyForeach of
+  ToJSONKeyTextForall keyToText _ -> toJSON $ M.foldlWithKey'
+    ( \hm key val -> HM.insert (keyToText (Pair s key)) (toJSONForeach s val) hm
+    ) HM.empty m
+  ToJSONKeyValueForall keyToValue _ -> toJSON $ M.foldrWithKey' 
+    ( \key val xs -> (keyToValue (Pair s key), toJSONForeach s val) : xs
+    ) [] m
+
+-- | Parse a 'Map' whose key type is higher-kinded. This only creates a valid 'Map'
+--   if the 'OrdForeach' instance agrees with the 'Ord' instance.
+parseJSONMapForeachKey :: forall k (f :: k -> Type) (a :: k) v. (FromJSONKeyForeach f, OrdForeach f, Unreify k)
+  => (Aeson.Value -> Aeson.Parser v)
+  -> Sing a
+  -> Aeson.Value
+  -> Aeson.Parser (Map (f a) v)
+parseJSONMapForeachKey valueParser s obj = unreify s $ case fromJSONKeyForeach of
+  FromJSONKeyTextParserForeach f -> Aeson.withObject "Map k v"
+    ( fmap (M.mapKeysMonotonic getApplyForeach) . KM.foldrWithKey
+      (\k v m -> M.insert
+        <$> (coerce (f s k :: Aeson.Parser (f a)) :: Aeson.Parser (ApplyForeach f a)) <?> Key k
+        <*> valueParser v <?> Key k
+        <*> m
+      ) (pure M.empty)
+    ) obj
+  FromJSONKeyValueForeach f -> Aeson.withArray "Map k v"
+    ( fmap (M.mapKeysMonotonic getApplyForeach . M.fromList)
+    . (coerce :: Aeson.Parser [(f a, v)] -> Aeson.Parser [(ApplyForeach f a, v)])
+    . TRV.sequence
+    . zipWith (parseIndexedJSONPair (f s) valueParser) [0..]
+    . V.toList
+    ) obj
+
+-- copied from aeson
+parseIndexedJSONPair :: (Aeson.Value -> Aeson.Parser a) -> (Aeson.Value -> Aeson.Parser b) -> Int -> Aeson.Value -> Aeson.Parser (a, b)
+parseIndexedJSONPair keyParser valParser idx value = p value <?> Index idx
+  where
+    p = Aeson.withArray "(k,v)" $ \ab ->
+        let n = V.length ab
+        in if n == 2
+             then (,) <$> parseJSONElemAtIndex keyParser 0 ab
+                      <*> parseJSONElemAtIndex valParser 1 ab
+             else fail $ "cannot unpack array of length " ++
+                         show n ++ " into a pair"
+{-# INLINE parseIndexedJSONPair #-}
+
+-- copied from aeson
+parseJSONElemAtIndex :: (Aeson.Value -> Aeson.Parser a) -> Int -> V.Vector Aeson.Value -> Aeson.Parser a
+parseJSONElemAtIndex p idx ary = p (V.unsafeIndex ary idx) <?> Index idx
