diff --git a/Example.hs b/Example.hs
new file mode 100644
--- /dev/null
+++ b/Example.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE Haskell2010, TemplateHaskell, QuasiQuotes #-}
+
+module Main where
+
+
+import Text.Printf (printf)
+
+import Text.DeadSimpleJSON
+import Text.DeadSimpleJSON.TH
+
+import Data.Ratio
+
+
+main :: IO ()
+main = do
+    
+    let jsonData = read "{\"seven\": 7, \"nine\": [1,2,4,8,16]}"
+    print $ (jsonData ? "nine[3]" :: Int)
+
+    let jone = [json|
+                    [
+                        {
+                            "one": 0.1,
+                            "two": 123
+                        },
+                        {
+                            "one": true,
+                            "two": null,
+                            "three": 23412349.24e-12
+                        },
+                        {
+                            "one": "ONE",
+                            "two": null,
+                            "three": "THREE"
+                        },
+                        {
+                            "one": false,
+                            "two": 14964674393249287
+                        }
+                    ]
+                |]
+        jtwo = jone -- [jsonF|json2.txt|]
+        jtri = [json| ["Naks", "Noks", "Nuks"] |]
+        jfrr = jone -- read [sF|json2.txt|] :: JSON
+
+        val1 = [jsq| jone[3].two |] :: String
+        val2 = [jsq| jtwo[4] |]     :: Double
+        val3 = [jsq| jtri |]        :: String
+
+    print $ length $ show jfrr
+    print $ length $ show jtwo
+
+    print val1
+    print val2
+    print val3
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,18 @@
+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.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+
+main = defaultMain
+
diff --git a/dead-simple-json.cabal b/dead-simple-json.cabal
new file mode 100644
--- /dev/null
+++ b/dead-simple-json.cabal
@@ -0,0 +1,44 @@
+Name:           dead-simple-json
+Version:        0.1.2
+Synopsis:       Dead simple JSON parser, with some Template Haskell sugar.
+Description:    This is dead simple JSON, consisting of a simple parser built with Parsec
+                and some Template Haskell syntactic sugar (which you may or may not use,
+                it works without).
+               
+License:        MIT
+License-File:   LICENSE
+Author:         Julian Fleischer <julian.fleischer@fu-berlin.de>
+Maintainer:     Julian Fleischer <julian.fleischer@fu-berlin.de>
+Build-Type:     Simple
+Cabal-Version:  >= 1.6
+Category:       JSON
+Stability:      experimental
+Homepage:       http://hub.darcs.net/scravy/dead-simple-json
+
+Extra-Source-Files: Example.hs
+
+Source-Repository head
+    type: darcs
+    location: hub.darcs.net:dead-simple-json
+
+Source-Repository this
+    type: darcs
+    location: hub.darcs.net:dead-simple-json
+    tag: v0.1.2
+
+Library
+    Exposed-Modules:    Text.DeadSimpleJSON,
+                        Text.DeadSimpleJSON.Convert,
+                        Text.DeadSimpleJSON.Query,
+                        Text.DeadSimpleJSON.TH,
+                        Text.DeadSimpleJSON.Types
+                        
+    Build-Depends:      base >= 4 && < 5,
+                        transformers >= 0.3,
+                        parsec >= 3.1.3,
+                        vector >= 0.10,
+                        containers >= 0.4.2,
+                        template-haskell
+    Hs-Source-Dirs:     src
+
+
diff --git a/src/Text/DeadSimpleJSON.hs b/src/Text/DeadSimpleJSON.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/DeadSimpleJSON.hs
@@ -0,0 +1,248 @@
+{-# LANGUAGE Haskell2010 #-}
+{-# OPTIONS -Wall -O2
+    -fno-warn-unused-do-bind
+    -fno-warn-missing-signatures
+    -fno-warn-name-shadowing
+    -fno-warn-orphans #-}
+
+{- |
+Module      :  DeadSimpleJSON.hs
+Copyright   :  (c) Julian Fleischer
+License     :  MIT
+
+Maintainer  :  Julian Fleischer <julian.fleischer@fu-berlin.de>
+Stability   :  experimental
+Portability :  portable
+
+A simple approach for parsing JSON.
+
+To read JSON data use 'read'. To print JSON data use 'show':
+
+> let jsonData = read "[1,2,4,8,16]" :: JSON
+> putStrLn $ show jsonData
+
+You can query json data using '?'. Querying implies conversion,
+therefor you may need to specify the result type:
+
+> let jsonData = read "{\"seven\": 7, \"nine\": [1,2,4,8,16]}"
+> print $ (jsonData ? "nine[3]" :: Int)
+
+For tighter control use 'parse'. A more convenient way for
+creating JSON objects in source code or querying JSON data,
+is using Template Haskell. See @Text.SimpleJSON.TH@.
+
+The recommended way for importing this module is importing
+it qualified, like so:
+
+> import qualified Text.SimpleJSON as JSON
+> import Text.SimpleJSON (JSON)
+
+-}
+module Text.DeadSimpleJSON (
+    -- * Parsing strings
+    parse,
+    parse',
+    parseM,
+
+    -- * Basic data types
+    Value (..),
+    JSON,
+
+    -- ** Querying json data
+    (?),
+    top,
+
+    -- ** Conversion to and from
+    Convert (..)
+) where
+
+
+import Prelude hiding (True, False)
+import qualified Prelude
+
+import Data.Char (isControl)
+
+import qualified Data.Map as M
+import qualified Data.Vector as V
+
+import Text.Parsec hiding (parse)
+import Control.Applicative ((*>), (<*))
+import Data.Functor.Identity
+
+import Numeric (showHex, readHex)
+
+import Text.DeadSimpleJSON.Convert
+import Text.DeadSimpleJSON.Query
+import Text.DeadSimpleJSON.Types
+
+
+instance Show JSON where
+    show (JSON jsonObject) = write jsonObject
+
+instance Read JSON where
+    readsPrec _ =
+        either (const []) (:[]) . runIdentity . runParserT json () "-"
+
+
+parse :: String -> Either ParseError JSON
+-- ^ Parse a String for JSON data or return a ParseError.
+parse str = runIdentity $ runParserT json' () "-" str
+
+parse' :: String -> Maybe Value
+-- ^ Parses a top-level JSON object, returning Just a Value or Nothing.
+parse' = parseM
+
+parseM :: Monad m => String -> m Value
+-- ^ Purely Monadic version of 'parse''.
+parseM = either (fail . show) (return . top) . parse
+
+top :: JSON -> Value
+-- ^ Unwraps a top-level JSON object to a Value.
+top (JSON v) = v
+
+
+write x = case x of
+    (Number n e) -> writeNumber n e
+    (String s) -> '"' : writeString s
+    (Object m) -> writeObject m
+    (Array v)  -> writeArray v
+    True  -> "true"
+    False -> "false"
+    Null  -> "null"
+
+writeNumber n 0 = show n
+writeNumber n e = show n ++ "e" ++ show e
+
+writeString (x:xs)
+    | isControl x   = "\\u"  ++ showHex (fromEnum x) (writeString xs)
+    | x == '\x2028' = "\\u2028"
+    | x == '\x2029' = "\\u2029"
+    | x == '\\'     = "\\\\" ++ writeString xs
+    | x == '\"'     = "\\\"" ++ writeString xs
+    | otherwise     = x : writeString xs
+writeString [] = "\""
+
+writeArray arr
+    | V.null arr = "[]"
+    | otherwise  = '[' : (tail $ concat $ V.foldr (\v l -> "," : write v : l) ["]"] arr)
+-- note that using V.foldr' instead of V.foldr makes the SpecConstr optimizer go nuts (-fspec-constr)
+
+writeObject obj
+    | M.null obj = "{}"
+    | otherwise  = '{' : (tail $ concat $ M.foldrWithKey' (\k v l -> ",\"" : writeString k : ":" : write v : l) ["}"] obj)
+
+
+json' :: Monad m => ParsecT String () m JSON
+json  :: Monad m => ParsecT String () m (JSON, String)
+
+value, jsonString, number, negativeNumber, nonNegativeNumber, object, array
+    :: Monad m => ParsecT String () m Value
+
+stringChar, escapedChar
+    :: Monad m => ParsecT String () m Char
+
+keyValue
+    :: Monad m => ParsecT String () m (String, Value)
+
+mkNumber
+    :: Monad m => String -> String -> String -> ParsecT String u m Value
+
+
+json = do
+    val  <- spaces *> (object <|> array)
+    rest <- many anyToken
+    return (JSON val, rest)
+
+json' = do
+    val <- spaces >> (object <|> array) <* spaces
+    (char '\EOT' >> return ()) <|> eof
+    return $ JSON val
+
+
+value = jsonString
+    <|> number
+    <|> object
+    <|> array
+    <|> (string "true"  >> return True)
+    <|> (string "false" >> return False)
+    <|> (string "null"  >> return Null)
+
+jsonString = do
+    char '"'
+    str <- many (stringChar <|> escapedChar)
+    char '"'
+    return $ String str
+
+stringChar = satisfy (\x -> not (isControl x || (elem x "\\\"")))
+
+escapedChar = do
+    char '\\'
+    oneOf "\"\\/"
+      <|> (oneOf "bfnrt" >>= special)
+      <|> (char 'u' >> count 4 hexDigit >>= convert)
+      <?> "escape sequence: one of b, f, n, r, t, or uXXXX"
+        where
+            special chr = return $ case chr of
+                'b' -> '\b'
+                'f' -> '\f'
+                'n' -> '\n'
+                'r' -> '\r'
+                't' -> '\t'
+                _   -> undefined
+            convert str = do
+                let [(hex, _)] = readHex str
+                return $ toEnum hex
+
+number = negativeNumber <|> nonNegativeNumber
+
+negativeNumber = do
+    char '-'
+    (Number nom denom) <- nonNegativeNumber
+    return $ Number (negate nom) denom
+
+nonNegativeNumber = do
+    num <- digits <|> string "0"
+    mantisse <- option "" (char '.' *> many1 digit)
+    exp <- option "0" exponent
+    mkNumber num mantisse exp
+        where
+            digits = do
+                first <- oneOf ['1'..'9']
+                rest  <- many digit
+                return $ first : rest
+            exponent = do
+                oneOf "eE"
+                sign <- option '+' $ oneOf "+-"
+                exp  <- many1 digit
+                return $ sign : exp
+
+mkNumber str1 str2 ('+':str3) = mkNumber str1 str2 str3
+mkNumber str1 str2 str3 = do
+    let str2' = reverse $ dropWhile (== '0') $ reverse str2
+        [(nom, _)] = reads (str1 ++ str2')
+        [(exp, _)] = reads (str3)
+        exp'   = negate (fromIntegral (length str2') + negate exp)
+        num n d
+            | n == 0 = Number 0 0
+            | n `rem` 10 == 0 = num (n `quot` 10) (d+1)
+            | otherwise = Number n d
+    return $ num nom exp'
+
+object = do
+    pairs <- between (char '{') (char '}') $ do
+        spaces
+        sepBy keyValue (char ',' >> spaces)
+    return $ Object $ M.fromList pairs
+
+keyValue = do
+    (String key) <- jsonString <* char ':'
+    val <- between spaces spaces value
+    return (key, val)
+
+array = do
+    values <- between (char '[') (char ']') $ do
+        spaces
+        sepBy (value <* spaces) (char ',' >> spaces)
+    return $ Array $ V.fromList values
+
+
diff --git a/src/Text/DeadSimpleJSON/Convert.hs b/src/Text/DeadSimpleJSON/Convert.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/DeadSimpleJSON/Convert.hs
@@ -0,0 +1,183 @@
+{-# LANGUAGE Haskell2010,
+             ScopedTypeVariables,
+             FlexibleInstances,
+             TypeSynonymInstances,
+             OverlappingInstances #-}
+{-# OPTIONS -Wall -O2 #-}
+
+
+module Text.DeadSimpleJSON.Convert (
+    Value (..),
+    Convert (..)
+) where
+
+
+import Prelude hiding (True, False)
+import qualified Prelude
+
+import Data.Int
+import Data.Ratio
+import Text.DeadSimpleJSON.Types
+
+import qualified Data.Vector as V
+-- import qualified Data.Map as M
+
+
+default ()
+
+
+class Convert a where
+    convert :: Value -> a
+
+    convert' :: Value -> Maybe a
+    convert' n@(Number _ _) = return $ convert n
+    convert' _ = fail ""
+
+    toJSON :: a -> Value
+    toJSON = undefined
+
+
+instance Convert a => Convert (Maybe a) where
+    convert  = convert'
+    convert' = maybe Nothing Just . convert'
+
+    toJSON (Just a) = toJSON a
+    toJSON Nothing = Null
+
+
+instance Convert Value where
+    convert = id
+    convert' = return
+
+    toJSON = id
+
+
+instance Convert Bool where
+    convert True  = Prelude.True
+    convert (String "") = Prelude.False
+    convert (String _) = Prelude.True
+    convert (Number 0 _) = Prelude.False
+    convert (Number _ _) = Prelude.True
+    convert _ = Prelude.False
+
+    convert' True = return Prelude.True
+    convert' False = return Prelude.False
+    convert' _ = fail ""
+
+    toJSON (Prelude.True) = True
+    toJSON (Prelude.False) = False
+
+
+instance Convert String where
+    convert (String s) = s
+    convert (Number n e)
+        | e >= 10   = show e
+        | otherwise = show n ++ "e" ++ show e
+    convert (Array arr) = tail $ tail $ V.foldr (\v l -> ", " ++ convert v ++ l) "" arr
+    convert (Object _) = "{object}"
+    convert True  = "true"
+    convert False = "false"
+    convert Null  = "null"
+
+    convert' (String s) = return s
+    convert' _ = fail ""
+
+    toJSON = String
+
+
+instance Convert a => Convert [a] where
+    convert (Array v) = map convert $ V.toList v
+    convert _ = []
+
+    convert' arr@(Array _) = return $ convert arr
+    convert' _ = fail ""
+
+    toJSON = Array . V.fromList . map toJSON
+
+
+instance Convert Double where
+    convert (Number n e)
+        | e >= 0    = fromInteger (n * 10 ^ e) / 1.0
+        | otherwise = fromInteger n / fromInteger (10 ^ negate e)
+    convert (Object _) = 0/0
+    convert (Array _) = 0/0
+    convert Null = 0/0
+    convert v = def v
+
+
+instance Convert Float where
+    convert (Number n e)
+        | e >= 0    = fromInteger (n * 10 ^ e) / 1.0
+        | otherwise = fromInteger n / fromInteger (10 ^ negate e)
+    convert (Object _) = 0/0
+    convert (Array _) = 0/0
+    convert Null = 0/0
+    convert v = def v
+
+
+instance forall a. (Read a, Integral a) => Convert (Ratio a) where
+    convert (Number n e)
+        | e >= 0    = n' * 10 ^ e' % 1
+        | otherwise = n' % 10 ^ negate e'
+            where n' = fromInteger n :: a
+                  e' = fromInteger e :: a
+    convert v = def v % 1
+
+
+instance Convert Integer where
+    convert (Number n e) = int n e
+    convert v = def v
+
+    toJSON = flip Number 1
+
+
+instance Convert Int where
+    convert (Number n e) = fromInteger $ int n e
+    convert v = def v
+
+    toJSON = flip Number 1 . toInteger
+
+
+instance Convert Int8 where
+    convert (Number n e) = fromInteger $ int n e
+    convert v = def v
+
+    toJSON = flip Number 1 . toInteger
+
+
+instance Convert Int16 where
+    convert (Number n e) = fromInteger $ int n e
+    convert v = def v
+
+    toJSON = flip Number 1 . toInteger
+
+
+instance Convert Int32 where
+    convert (Number n e) = fromInteger $ int n e
+    convert v = def v
+
+    toJSON = flip Number 1 . toInteger
+
+    
+instance Convert Int64 where
+    convert (Number n e) = fromInteger $ int n e
+    convert v = def v
+
+    toJSON = flip Number 1 . toInteger
+
+
+int :: Integral a => a -> a -> a
+int n e
+    | e >= 0    = n * 10 ^ e
+    | otherwise = n `quot` 10 ^ negate e
+
+def :: (Read a, Num a) => Value -> a
+def True  = 1
+def False = 0
+def Null  = 0
+def (String s) = let v = reads s in case v of ((n, _):_) -> n; _ -> 0
+def (Array _)  = 0
+def (Object _) = 0
+def _ = undefined
+
+
diff --git a/src/Text/DeadSimpleJSON/Query.hs b/src/Text/DeadSimpleJSON/Query.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/DeadSimpleJSON/Query.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE Haskell2010,
+             DeriveDataTypeable #-}
+{-# OPTIONS -Wall -O2
+    -fno-warn-unused-do-bind
+    -fno-warn-missing-signatures
+    -fno-warn-name-shadowing #-}
+
+module Text.DeadSimpleJSON.Query (
+    query,
+    query',
+    queryV,
+    queryV',
+    Query (..),
+    mkQuery,
+    mkQuery',
+    (?)
+) where
+
+
+import Text.Parsec
+
+import Text.DeadSimpleJSON.Convert
+import Text.DeadSimpleJSON.Types
+
+import qualified Data.Map as M
+import qualified Data.Vector as V
+
+import Data.Data
+import Data.Functor.Identity
+import Control.Monad
+import Control.Applicative ((<*))
+
+
+data Query = Field String Query
+           | Index Int Query
+           | Read
+    deriving (Show, Data, Typeable)
+
+
+query :: Convert a => Query -> JSON -> a
+query q (JSON v) = queryV q v
+
+query' :: Convert a => Query -> JSON -> Maybe a
+query' q (JSON v) = queryV' q v
+
+
+queryV :: Convert a => Query -> Value -> a
+queryV (Field f q) (Object m) = maybe (convert Null) (queryV q) (M.lookup f m)
+queryV (Index i q) (Array a)  = maybe (convert Null) (queryV q) (a V.!? i)
+queryV Read v = convert v
+
+queryV _ _ = convert Null
+
+
+queryV' :: Convert a => Query -> Value -> Maybe a
+queryV' (Field f q) (Object m) = maybe Nothing (queryV' q) (M.lookup f m)
+queryV' (Index i q) (Array a)  = maybe Nothing (queryV' q) (a V.!? i)
+queryV' Read v = convert' v
+
+queryV' _ _ = Nothing
+
+
+json ? q = query (mkQuery q) json
+
+
+type Parser a = ParsecT String () Identity a
+
+ident :: Parser String
+ident = liftM2 (:) (letter <|> char '_') (many (alphaNum <|> char '_'))
+
+index :: Parser Int
+index = liftM read $ between (char '[') (char ']') (many1 digit)
+
+path :: Parser [Either String Int]
+path = liftM concat $ sepBy element (char '.')
+
+element :: Parser [Either String Int]
+element = liftM2 (:) (ident >>= return . Left) (many index >>= return . map Right)
+
+mkPath :: String -> [Either String Int]
+mkPath = either (const []) id . parse path "-"
+
+mkQuery :: String -> Query
+mkQuery = buildQuery . mkPath
+
+mkQuery' :: String -> Either ParseError Query
+mkQuery' = either Left (Right . buildQuery) . parse (path <* eof) "JSON Query"
+
+buildQuery = foldr (\x p -> either (\s -> Field s p) (\i -> Index i p) x) Read
+
+
diff --git a/src/Text/DeadSimpleJSON/TH.hs b/src/Text/DeadSimpleJSON/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/DeadSimpleJSON/TH.hs
@@ -0,0 +1,161 @@
+{-# LANGUAGE Haskell2010,
+             TemplateHaskell #-}
+{-# OPTIONS -Wall -O2 -fno-warn-name-shadowing #-}
+
+-- | Template Haskell syntax sugar for working with 'JSON' data.
+-- 
+-- For using this module, you need to declare a LANGUAGE
+-- pragma like the following:
+-- 
+-- > {-# LANGUAGE Haskell2010, TemplateHaskell, QuasiQuotes #-}
+module Text.DeadSimpleJSON.TH (
+
+    -- * Query JSON objects
+    jsq,
+
+    -- * Create JSON objects
+    json,
+    jsonF,
+
+    -- * Include strings
+    s,
+    sF
+) where
+
+import Prelude hiding (True, False)
+import qualified Prelude
+
+import Data.Char
+import qualified Data.Map as M
+import qualified Data.Vector as V
+
+import Text.DeadSimpleJSON (parse)
+import Text.DeadSimpleJSON.Convert (Convert (..))
+import Text.DeadSimpleJSON.Query
+import Text.DeadSimpleJSON.Types
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+
+
+s :: QuasiQuoter
+-- ^ A QuasiQuoter on raw strings.
+--
+-- The definition is basically:
+--
+-- > s = QuasiQuoter {
+-- >   quoteExp  = return . LitE . StringL
+-- > }
+s = QuasiQuoter {
+    quoteExp  = return . LitE . StringL,
+
+    quotePat  = \_ -> fail "illegal string QuasiQuote (allowed as expression only, used as a pattern)",
+    quoteType = \_ -> fail "illegal string QuasiQuote (allowed as expression only, used as a type)",
+    quoteDec  = \_ -> fail "illegal string QuasiQuote (allowed as expression only, used as a dec)"
+}
+
+
+sF :: QuasiQuoter
+-- ^ A QuasiQuoter which includes raw strings from files.
+--
+-- The following example will include the contents of @file.txt@
+-- as a @String@.
+--
+-- > let str = [sF|file.txt|]
+--
+-- Note that every character inside the brackets is treated
+-- as part of the file name, that is @[sF| file.txt |]@ is not
+-- the same as the above example (it will try to find a file which
+-- name includes space characters).
+sF = quoteFile s
+
+jsonF :: QuasiQuoter
+-- ^ A QuasiQuoter which includes JSON data from files.
+--
+-- The following example will include the contents of @data.json@
+-- as 'JSON'.
+--
+-- > let str = [jsonF|data.json|]
+--
+-- Note that every character inside the brackets is treated
+-- as part of the file name, that is @[jsonF| data.json |]@ is not
+-- the same as the above example (it will try to find a file which
+-- name includes space characters).
+
+jsonF = quoteFile json
+
+json :: QuasiQuoter
+-- ^ A QuasiQuoter which includes JSON data.
+--
+-- The type of the expression is 'JSON'.
+json = QuasiQuoter {
+    quoteExp  = jsonQuoter,
+
+    quotePat  = \_ -> fail "illegal json QuasiQuote (allowed as expression only, used as a pattern)",
+    quoteType = \_ -> fail "illegal json QuasiQuote (allowed as expression only, used as a type)",
+    quoteDec  = \_ -> fail "illegal json QuasiQuote (allowed as expression only, used as a dec)"
+}
+
+jsonQuoter :: String -> Q Exp
+jsonQuoter = either (fail . show) buildJSON . parse
+    where
+        buildJSON (JSON json) = do
+            json' <- buildJSON' json
+            return (AppE (ConE 'JSON) json')
+
+        buildJSON' (String s) = return $ AppE (ConE 'String) (LitE (StringL s))
+        buildJSON' (Number n e) = return $ AppE (AppE (ConE 'Number) (LitE (IntegerL n))) (LitE (IntegerL e))
+        buildJSON' (Object obj) = do
+            m <- mapM (\(k, v) -> do { x <- buildJSON' v; return $ TupE [LitE (StringL k), x] }) (M.toList obj)
+            return $ AppE (ConE 'Object) (AppE (VarE 'M.fromList) (ListE m))
+        buildJSON' (Array arr) = do
+            v <- mapM buildJSON' (V.toList arr)
+            return $ AppE (ConE 'Array) (AppE (VarE 'V.fromList) (ListE v))
+        buildJSON' True = return $ ConE 'True
+        buildJSON' False = return $ ConE 'False
+        buildJSON' Null = return $ ConE 'Null
+
+
+jsq :: QuasiQuoter
+-- ^ A QuasiQuoter which queries a json object using JavaScript notation.
+-- 
+-- Suppose obj contains a json object of type JSON:
+--
+-- > [jsq| obj.prop.list[3] |]
+--
+-- The above will query the object in obj as if it was JavaScript.
+--
+-- The type of the expression is polymorphic: @Convert a => a@.
+--
+-- You will need to specify the type of the query, like so:
+--
+-- > [jsq| obj.prop.list |] :: [Integer]
+--
+-- For possible conversions, see the instances for 'Convert'.
+jsq = QuasiQuoter {
+    quoteExp  = jsqQuoter,
+
+    quotePat  = \_ -> fail "illegal jsq QuasiQuote (allowed as expression only, used as a pattern)",
+    quoteType = \_ -> fail "illegal jsq QuasiQuote (allowed as expression only, used as a type)",
+    quoteDec  = \_ -> fail "illegal jsq QuasiQuote (allowed as expression only, used as a dec)"
+}
+
+jsqQuoter :: String -> Q Exp
+jsqQuoter = either (fail . show) buildQuery . mkQuery' . filter (not . isSpace)
+    where
+        buildQuery (Field s e) = do
+            q <- buildQuery' e
+            return $ AppE ((AppE (VarE 'query)) q) (VarE (mkName s))
+        buildQuery _ = do
+            report Prelude.False "Warning: Empty JSON Query"
+            [| convert $ Object M.empty |]
+
+        buildQuery' (Field s e) = do
+            exp <- buildQuery' e
+            return $ AppE (AppE (ConE 'Field) (LitE (StringL s))) exp
+        buildQuery' (Index i e) = do
+            exp <- buildQuery' e
+            return $ AppE (AppE (ConE 'Index) (LitE (IntegerL (fromIntegral i)))) exp
+        buildQuery' (Read) = return $ ConE 'Read
+
+
diff --git a/src/Text/DeadSimpleJSON/Types.hs b/src/Text/DeadSimpleJSON/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/DeadSimpleJSON/Types.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE Haskell2010,
+             DeriveDataTypeable #-}
+{-# OPTIONS -Wall -O2 #-}
+
+-- | The basic JSON data types.
+module Text.DeadSimpleJSON.Types (
+    Value (..),
+    JSON (..)
+) where
+
+
+import Data.Data
+import Data.Map (Map)
+import Data.Vector (Vector)
+
+
+-- | A top-level JSON object.
+--
+-- Merely a wrapper that ensures that no other 'Value's
+-- but 'Array' and 'Object' reside at the top-level.
+newtype JSON = JSON Value
+    deriving (Eq, Data, Typeable)
+
+-- | A JSON value.
+data Value
+
+    = String String
+    -- ^ A JSON String, represented as ordinary Haskell String.
+
+    | Number !Integer !Integer
+    -- ^ A JSON Number, represented by two 'Integer's in
+    -- exponontial form. @Number n e@ is the same as @{n}e{exp}@,
+    -- that is @n * 10 ^ e@. This allows for arbitrary precision
+    -- fixed point rationals. See 'Convert' for easy conversions.
+
+    | Object (Map String Value)
+    -- ^ A JSON Object, represented as 'Map'.
+
+    | Array  (Vector Value)
+    -- ^ A JSON Array, represented as 'Vector' of Values.
+
+    | True
+    -- ^ True.
+
+    | False
+    -- ^ False.
+
+    | Null
+    -- ^ Null (void, unit, @()@).
+
+    deriving (Eq, Show, Read, Data, Typeable)
+
+
