on master help sign in
Add an accessor for optional object fields.
commitb4d4b901664bfe41dc8a326211ea579b632f2e87 authorBryan O'Sullivan <bos@mailrank.com> dateWed 26 Jan 2011, 18:38 (16 years ago) parent70f5697
2 files changed+52−2
Data/Aeson.hs+1 Data/Aeson/Types.hs+51−2
Data/Aeson.hs+1
@@ -21,6 +21,7 @@ module Data.Aeson
2121 -- * Constructors and accessors
2222 , (.=)
2323 , (.:)
24+ , (.:?)
2425 , object
2526 -- * Encoding and parsing
2627 , encode
Data/Aeson/Types.hs+51−2
@@ -21,13 +21,18 @@ module Data.Aeson.Types
2121 -- * Constructors and accessors
2222 , (.=)
2323 , (.:)
24+ , (.:?)
2425 , object
2526 ) where
2627
2728import Control.Applicative
2829import Control.DeepSeq (NFData(..))
2930import Data.Map (Map)
31+import qualified Data.ByteString as B
32+import qualified Data.ByteString.Lazy as LB
33+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
3034import Data.Text (Text, pack, unpack)
35+import qualified Data.Text.Lazy as LT
3136import Data.Time.Clock (UTCTime)
3237import Data.Time.Format (formatTime, parseTime)
3338import Data.Typeable (Typeable)
@@ -62,14 +67,31 @@ name .= value = M.singleton name (toJSON value)
6267{-# INLINE (.=) #-}
6368
6469-- | Retrieve the value associated with the given key of an 'Object'.
65−-- The result is 'empty' if the key is not present or cannot be
66−-- converted to the desired type..
70+-- The result is 'empty' if the key is not present or the value cannot
71+-- be converted to the desired type.
72+--
73+-- This accessor is appropriate if the key and value /must/ be present
74+-- in an object for it to be valid. If the key and value are
75+-- optional, use '(.:?)' instead.
6776(.:) :: (Alternative f, FromJSON a) => Object -> Text -> f a
6877obj .: key = case M.lookup key obj of
6978 Nothing -> empty
7079 Just v -> fromJSON v
7180{-# INLINE (.:) #-}
7281
82+-- | Retrieve the value associated with the given key of an 'Object'.
83+-- The result is 'Nothing' if the key is not present, or 'empty' if
84+-- the value cannot be converted to the desired type.
85+--
86+-- This accessor is most useful if the key and value can be absent
87+-- from an object without affecting its validity. If the key and
88+-- value are mandatory, use '(.:?)' instead.
89+(.:?) :: (Alternative f, FromJSON a) => Object -> Text -> f (Maybe a)
90+obj .:? key = case M.lookup key obj of
91+ Nothing -> pure Nothing
92+ Just v -> fromJSON v
93+{-# INLINE (.:?) #-}
94+
7395-- | Create a 'Value' from a list of 'Object's. If duplicate
7496-- keys arise, earlier keys and their associated values win.
7597object :: [Object] -> Value
@@ -174,6 +196,33 @@ instance FromJSON Text where
174196 fromJSON _ = empty
175197 {-# INLINE fromJSON #-}
176198
199+instance ToJSON LT.Text where
200+ toJSON = String . LT.toStrict
201+ {-# INLINE toJSON #-}
202+
203+instance FromJSON LT.Text where
204+ fromJSON (String t) = pure (LT.fromStrict t)
205+ fromJSON _ = empty
206+ {-# INLINE fromJSON #-}
207+
208+instance ToJSON B.ByteString where
209+ toJSON = String . decodeUtf8
210+ {-# INLINE toJSON #-}
211+
212+instance FromJSON B.ByteString where
213+ fromJSON (String t) = pure . encodeUtf8 $ t
214+ fromJSON _ = empty
215+ {-# INLINE fromJSON #-}
216+
217+instance ToJSON LB.ByteString where
218+ toJSON = toJSON . B.concat . LB.toChunks
219+ {-# INLINE toJSON #-}
220+
221+instance FromJSON LB.ByteString where
222+ fromJSON (String t) = pure . LB.fromChunks . (:[]) . encodeUtf8 $ t
223+ fromJSON _ = empty
224+ {-# INLINE fromJSON #-}
225+
177226mapA :: (Applicative f) => (t -> f a) -> [t] -> f [a]
178227mapA f = go
179228 where