on master help sign in
Round tripping of special strings #31
2d71dd2Michael Snoyman
Data/Yaml.hs+13−1
@@ -86,6 +86,7 @@ import Data.Text.Encoding.Error (lenientDecode)
86import qualified Data.HashMap.Strict as M
86import qualified Data.HashMap.Strict as M
87import Data.Typeable
87import Data.Typeable
88import Data.Attoparsec.Number
88import Data.Attoparsec.Number
89+import qualified Data.HashSet as HashSet
89
90
90encode :: ToJSON a => a -> ByteString
91encode :: ToJSON a => a -> ByteString
91encode obj = unsafePerformIO $
92encode obj = unsafePerformIO $
@@ -123,7 +124,13 @@ objToEvents' (Object pairs) rest =
123-- https://github.com/snoyberg/yaml/issues/24
124-- https://github.com/snoyberg/yaml/issues/24
124objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest
125objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest
125
126
126−objToEvents' (String s) rest = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing : rest
127+objToEvents' (String s) rest =
128+ event : rest
129+ where
130+ event
131+ -- Make sure that special strings are encoded as strings properly.
132+ | s `HashSet.member` specialStrings = EventScalar (encodeUtf8 s) StrTag SingleQuoted Nothing
133+ | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing
127objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest
134objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest
128objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest
135objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest
129objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest
136objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest
@@ -134,6 +141,11 @@ pairToEvents (k, v) rest =
134 EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing
141 EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing
135 : objToEvents' v rest
142 : objToEvents' v rest
136
143
144+-- | Strings which must be escaped so as not to be treated as non-string scalars.
145+specialStrings :: HashSet.HashSet Text
146+specialStrings = HashSet.fromList $ T.words
147+ "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~"
148+
137-- Parsing
149-- Parsing
138
150
139data ParseException = NonScalarKey
151data ParseException = NonScalarKey
test/main.hs+6
@@ -116,6 +116,12 @@ main = hspec $ do
116 , hash = HM.fromList [("key1", "value1"), ("key2", "value2")]
116 , hash = HM.fromList [("key1", "value1"), ("key2", "value2")]
117 }
117 }
118
118
119+ describe "round-tripping of special scalars" $ do
120+ let special = words "y Y On ON false"
121+ forM_ special $ \w -> it w $
122+ let v = object ["word" .= w]
123+ in D.decode (D.encode v) `shouldBe` Just v
124+
119
125
120
126
121specialStrings :: [T.Text]
127specialStrings :: [T.Text]