diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, Sam Anklesaria
+
+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 Sam Anklesaria 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/Yesod/Test/Json.hs b/Yesod/Test/Json.hs
new file mode 100644
--- /dev/null
+++ b/Yesod/Test/Json.hs
@@ -0,0 +1,79 @@
+-- | Yesod.Test.Json provides convenience functions for working
+--   with Test.Hspec and Network.Wai.Test on JSON data.
+module Yesod.Test.Json (
+	testApp,
+	APIFunction,
+	assertBool,
+	assertString,
+	assertOK,
+	assertJSON,
+	Session(..),
+	H.Assertion,
+	module Test.Hspec,
+	module Data.Aeson
+	) where
+import qualified Test.HUnit as H
+import qualified Data.ByteString.Lazy.Char8 as L8
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.Text (Text)
+import Data.Aeson
+import Network.HTTP.Types
+import Test.Hspec
+import Network.Wai
+import Network.Wai.Test
+import Control.Monad.IO.Class
+import Yesod.Default.Config
+import Data.Conduit.List
+
+-- | A request to your server. 
+type APIFunction = ByteString -- ^ method
+				   -> [Text] -- ^ path
+				   -> Value -- JSON data
+				   -> Session SResponse
+
+-- Assert a boolean value
+assertBool :: String -> Bool -> Session ()
+assertBool s b = liftIO $ H.assertBool s b
+
+-- Fail a test with an error string
+assertString :: String -> Session ()
+assertString = liftIO . H.assertString
+
+-- Assert a 200 response code
+assertOK :: SResponse -> Session ()
+assertOK SResponse{simpleStatus = s, simpleBody = b} = assertBool (concat
+    [ "Expected status code 200, but received " 
+    , show sc
+    , ". Response body: "
+    , show (L8.unpack b)
+    ]) $ sc == 200
+  where
+    sc = statusCode s
+
+-- Assert a JSON body meeting some requirement
+assertJSON :: (ToJSON a, FromJSON a) => (a -> (String, Bool)) -> SResponse -> Session ()
+assertJSON f SResponse{simpleBody = lbs} = do
+	case decode lbs of
+		Nothing -> assertString $ "Invalid JSON: "  ++ show (L8.unpack lbs)
+		Just a ->
+			case fromJSON a of
+				Error s -> assertString (concat [s, "\nInput JSON: ", show a])
+				Success x -> uncurry assertBool (f x)
+
+-- | Make a request to your server
+apiRequest :: AppConfig env extra -> APIFunction
+apiRequest conf m p x = srequest $ SRequest r (encode x) where
+    r = defaultRequest {
+        serverPort = appPort conf,
+        requestBody = sourceList . L.toChunks $ encode x,
+        requestMethod = m,
+        pathInfo = p
+    }
+
+-- | Run a test suite for your 'Application'
+testApp :: Application -> AppConfig env extra ->
+		  (((APIFunction -> Session ()) -> H.Assertion) -> Spec) -> IO ()
+testApp app conf specfun = do
+	let apiTest f = runSession (f (apiRequest conf)) app
+	hspec $ (specfun apiTest)
diff --git a/yesod-test-json.cabal b/yesod-test-json.cabal
new file mode 100644
--- /dev/null
+++ b/yesod-test-json.cabal
@@ -0,0 +1,25 @@
+-- Initial yesod-test-json.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                yesod-test-json
+version:             0.1.0.0
+synopsis:            Utility functions for testing JSON web services written in Yesod
+description:         yesod-test-json provides combinators for using the hspec and wai-test libraries together.
+                     It is meant to be used like yesod-test, but for web services as opposed to web applications.
+homepage:            https://github.com/bogiebro/yesod-test-json
+license:             BSD3
+license-file:        LICENSE
+author:              Sam Anklesaria
+maintainer:          amsay@amsay.net
+-- copyright:           
+category:            Web
+build-type:          Simple
+cabal-version:       >=1.8
+source-repository head
+  type:     git
+  location: git://github.com/bogiebro/yesod-test-json.git
+
+library
+  exposed-modules:     Yesod.Test.Json
+  -- other-modules:       
+  build-depends:       base ==4.5.*, HUnit ==1.2.*, bytestring ==0.9.*, text ==0.11.*, aeson ==0.6.*, http-types ==0.6.*, hspec ==1.3.*, wai ==1.2.*, wai-test ==1.2.*, transformers ==0.3.*, yesod-default ==1.0.*, conduit ==0.4.*
