Bryan O'Sullivan avatar Bryan O'Sullivan committed 0df8973

Escape control characters properly.

Comments (0)

Files changed (1)

Data/Aeson/Encode.hs

 import Blaze.ByteString.Builder
 import Blaze.ByteString.Builder.Char.Utf8
 import Data.Aeson.Types (ToJSON(..), Value(..))
-import Data.Monoid (mappend, mconcat)
+import Data.Monoid (mappend)
+import Numeric (showHex)
 import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy.Char8 as L
 import qualified Data.Map as M
 string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
   where
     quote q = case T.uncons t of
-                Just (c,t') -> mconcat [fromText h, fromText (escape c),
-                                        quote t']
+                Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
                 Nothing -> fromText h
         where (h,t) = T.break isEscape q
-    isEscape c = c == '\"' || c == '\n' || c == '\r' || c == '\t'
-    escape '\"' = "\\\""
-    escape '\n' = "\\n"
-    escape '\r' = "\\r"
-    escape '\t' = "\\t"
-    escape _    = error "Data.Aeson.Encode.build: internal error"
+    isEscape c = c == '\"' || c == '\\' || c < '\x20'
+    escape '\"' = fromByteString "\\\""
+    escape '\\' = fromByteString "\\\\"
+    escape '\n' = fromByteString "\\n"
+    escape '\r' = fromByteString "\\r"
+    escape '\t' = fromByteString "\\t"
+    escape c
+        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
+        | otherwise  = fromChar c
+        where h = showHex (fromEnum c) ""
 
 encode :: ToJSON a => a -> L.ByteString
 encode = toLazyByteString . build . toJSON
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.