dead-simple-json (empty) → 0.1.2
raw patch · 9 files changed
+860/−0 lines, 9 filesdep +basedep +containersdep +parsecsetup-changed
Dependencies added: base, containers, parsec, template-haskell, transformers, vector
Files
- Example.hs +58/−0
- LICENSE +18/−0
- Setup.lhs +4/−0
- dead-simple-json.cabal +44/−0
- src/Text/DeadSimpleJSON.hs +248/−0
- src/Text/DeadSimpleJSON/Convert.hs +183/−0
- src/Text/DeadSimpleJSON/Query.hs +91/−0
- src/Text/DeadSimpleJSON/TH.hs +161/−0
- src/Text/DeadSimpleJSON/Types.hs +53/−0
+ Example.hs view
@@ -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+++
+ LICENSE view
@@ -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.+
+ Setup.lhs view
@@ -0,0 +1,4 @@+import Distribution.Simple++main = defaultMain+
+ dead-simple-json.cabal view
@@ -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++
+ src/Text/DeadSimpleJSON.hs view
@@ -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++
+ src/Text/DeadSimpleJSON/Convert.hs view
@@ -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++
+ src/Text/DeadSimpleJSON/Query.hs view
@@ -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++
+ src/Text/DeadSimpleJSON/TH.hs view
@@ -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++
+ src/Text/DeadSimpleJSON/Types.hs view
@@ -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)++