@@ -0,0 +1,55 @@
1+{-# LANGUAGE OverloadedStrings #-}
3+module Data.Aeson.Encode
9+import Blaze.ByteString.Builder
10+import Blaze.ByteString.Builder.Char.Utf8
11+import Data.Aeson.Types (JSON(..), Value(..))
12+import Data.Monoid (mappend, mconcat)
13+import qualified Data.ByteString.Char8 as B
14+import qualified Data.ByteString.Lazy.Char8 as L
15+import qualified Data.Map as M
16+import qualified Data.Text as T
17+import qualified Data.Vector as V
19+build :: Value -> Builder
20+build Null = fromByteString "null"
21+build (Bool b) = fromByteString $ if b then "true" else "false"
22+build (Number n) = fromByteString (B.pack (show n))
23+build (String s) = string s
25+ | V.null v = fromByteString "[]"
26+ | otherwise = fromChar '[' `mappend`
27+ build (V.unsafeHead v) `mappend`
28+ V.foldr f (fromChar ']') (V.unsafeTail v)
29+ where f a z = fromChar ',' `mappend` build a `mappend` z
32+ (x:xs) -> fromChar '{' `mappend`
34+ foldr f (fromChar '}') xs
35+ _ -> fromByteString "{}"
36+ where f a z = fromChar ',' `mappend` one a `mappend` z
37+ one (k,v) = string k `mappend` fromChar ':' `mappend` build v
39+string :: T.Text -> Builder
40+string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
42+ quote s = case T.uncons t of
43+ Just (c,t') -> mconcat [fromText h, fromText (escape c),
45+ Nothing -> fromText h
46+ where (h,t) = T.break isEscape s
47+ isEscape c = c == '\"' || c == '\n' || c == '\r' || c == '\t'
53+encode :: JSON a => a -> L.ByteString
54+encode = toLazyByteString . build . toJSON