diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Andrew Rademacher
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/aeson-casing.cabal b/aeson-casing.cabal
new file mode 100644
--- /dev/null
+++ b/aeson-casing.cabal
@@ -0,0 +1,44 @@
+
+name:                aeson-casing
+version:             0.1.0.0
+synopsis:            Tools to change the formatting of field names in Aeson 
+                     instances.
+description:         Tools to change the formatting of field names in Aeson 
+                     instances. This includes CamelCasing, Pascal Casing and
+                     Snake Casing.
+license:             MIT
+license-file:        LICENSE
+author:              Andrew Rademacher
+maintainer:          andrewrademacher@gmail.com
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.10
+
+source-repository head
+    type:               git
+    location:           https://github.com/AndrewRademacher/aeson-casing.git
+
+library
+    hs-source-dirs:     src
+    default-language:   Haskell2010
+
+    exposed-modules:    Data.Aeson.Casing.Internal
+                    ,   Data.Aeson.Casing
+
+    build-depends:      base                >=4.7   && <4.8
+                    ,   aeson               >=0.8   && <0.9
+
+test-suite casing
+    type:               exitcode-stdio-1.0
+    main-is:            Main.hs
+    hs-source-dirs:     test
+    default-language:   Haskell2010
+
+    build-depends:      base                >=4.7   && <4.8
+                    ,   tasty
+                    ,   tasty-quickcheck
+                    ,   tasty-hunit
+                    ,   tasty-th
+
+                    ,   aeson
+                    ,   aeson-casing
diff --git a/src/Data/Aeson/Casing.hs b/src/Data/Aeson/Casing.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aeson/Casing.hs
@@ -0,0 +1,31 @@
+-- | The casing utilities allow you to specify how Aeson renders and parses
+-- the field names in JSON messages. Snake, Camel, and Pascal case are all
+-- supported. To include casing modifiers in Aeson, attach options to instances
+-- of ToJSON and FromJSON.
+--
+-- > data Person = Person
+-- >        { personFirstName :: Text
+-- >        , personLastName  :: Text
+-- >        } deriving (Generic)
+-- >
+-- > instance ToJSON Person where
+-- >    toJSON = genericToJSON $ aesonPrefix snakeCase
+-- > instance FromJSON Person where
+-- >    parseJSON = genericParseJSON $ aesonPrefix snakeCase
+--
+-- The above code will produce JSON messages like the following...
+--
+-- > {
+-- >    "first_name": "John",
+-- >    "last_name": "Doe"
+-- > }
+module Data.Aeson.Casing
+    ( aesonDrop
+    , aesonPrefix
+
+    , snakeCase
+    , camelCase
+    , pascalCase
+    ) where
+
+import           Data.Aeson.Casing.Internal
diff --git a/src/Data/Aeson/Casing/Internal.hs b/src/Data/Aeson/Casing/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aeson/Casing/Internal.hs
@@ -0,0 +1,69 @@
+module Data.Aeson.Casing.Internal where
+
+import           Data.Aeson.Types
+import           Data.Char
+
+-- | Creates an Aeson options object that drops a specific number of characters
+-- from the front of a field name, then applies a casing function.
+aesonDrop :: Int -> (String -> String) -> Options
+aesonDrop n f = defaultOptions
+        { fieldLabelModifier = f . drop n }
+
+-- | Creates an Aeson options object that drops the field name prefix from a
+-- field, then applies a casing function. We assume a convention of the prefix
+-- always being lower case, and the first letter of the actual field name being
+-- uppercase. This accommodated for field names in GHC 7.8 and below.
+--
+-- > data Person = Person
+-- >        { personFirstName :: Text
+-- >        , personLastName  :: Text
+-- >        } deriving (Generic)
+-- >
+-- > data Dog = Dog
+-- >        { dogFirstName :: Text
+-- >        } deriving (Generic)
+--
+-- In the above cases, dog and person are always dropped from the JSON field
+-- names.
+aesonPrefix :: (String -> String) -> Options
+aesonPrefix f = defaultOptions
+        { fieldLabelModifier = f . dropFPrefix }
+
+----
+
+-- | Snake casing, where the words are always lower case and separated by an
+-- underscore.
+snakeCase :: String -> String
+snakeCase = u . applyFirst toLower
+    where u []                 = []
+          u (x:xs) | isUpper x = '_' : toLower x : snakeCase xs
+                   | otherwise = x : u xs
+
+-- | Camel casing, where the words are separated by the first letter of each
+-- word being a capitol. However, the first letter of the field is never a
+-- capitol.
+camelCase :: String -> String
+camelCase = applyFirst toLower
+
+-- | Pascal casing, where the words are separated by the first letter of each
+-- word being a capitol. The first letter of the field is always a capitol.
+pascalCase :: String -> String
+pascalCase = applyFirst toUpper
+
+----
+
+applyFirst :: (Char -> Char) -> String -> String
+applyFirst _ []     = []
+applyFirst f [x]    = [f x]
+applyFirst f (x:xs) = f x: xs
+
+dropFPrefix :: String -> String
+dropFPrefix []                 = []
+dropFPrefix (x:xs) | isUpper x = x : xs
+                   | otherwise = dropFPrefix xs
+
+dropCPrefix :: String -> String
+dropCPrefix [] = []
+dropCPrefix [x] = [x]
+dropCPrefix (x0:x1:xs) | isLower x1 = x0 : x1 : xs
+                       | otherwise  = dropCPrefix (x1 : xs)
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,10 @@
+module Main where
+
+import           Test.Tasty
+
+import qualified Data.Aeson.Casing.Test as Casing
+
+main :: IO ()
+main = defaultMain $ testGroup "Tests"
+        [ Casing.tests
+        ]
