Copyright | (c) Scrive 2011 |
---|---|
License | BSD-style (see the LICENSE file in the distribution) |
Maintainer | mariusz@scrive.com |
Stability | development |
Portability | portable |
Safe Haskell | None |
Language | Haskell98 |
Interface for extracting data from JSValue.
Synopsis
- class FromJSValue a where
- fromJSValue :: JSValue -> Maybe a
- fromJSValueM :: (JSValueContainer c, MonadReader c m) => m (Maybe a)
- class FromJSValueWithUpdate a where
- fromJSValueWithUpdate :: Maybe a -> JSValue -> Maybe a
- fromJSValueWithUpdateM :: (JSValueContainer c, MonadReader c m) => Maybe a -> m (Maybe a)
- class MatchWithJSValue a where
- matchesWithJSValue :: a -> JSValue -> Bool
- matchesWithJSValueM :: (JSValueContainer c, MonadReader c m) => a -> m Bool
- jsValueField :: (JSValueContainer c, MonadReader c m, FromJSValue a) => String -> m (Maybe (Maybe a))
- fromJSValueField :: (JSValueContainer c, MonadReader c m, FromJSValue a) => String -> m (Maybe a)
- fromJSValueFieldBase64 :: (JSValueContainer c, MonadReader c m) => String -> m (Maybe ByteString)
- fromJSValueFieldCustom :: (JSValueContainer c, MonadReader c m) => String -> m (Maybe a) -> m (Maybe a)
- fromJSValueCustomMany :: (JSValueContainer c, MonadReader c m) => m (Maybe a) -> m (Maybe [a])
- fromJSValueCustomList :: (JSValueContainer c, MonadReader c m) => [m (Maybe a)] -> m (Maybe [a])
- fromJSValueManyWithUpdate :: (JSValueContainer c, MonadReader c m, FromJSValueWithUpdate a, MatchWithJSValue a) => [a] -> m (Maybe [a])
- withJSValue :: Monad m => JSValue -> ReaderT JSValue m a -> m a
Basic Parsing
class FromJSValue a where Source #
Structures that can be parsed
from JSON. Instances must declare
either fromJSValue
(parse directly from JSValue
) or
fromJSValueM
(uses MonadReader
).
Example implementation:
data D = D String Int instance FromJSValue D where fromJSValue = do s <- fromJSValue "string_key" i <- fromJSValue "int_key" return (D <$> s <*> i)
Note that we make use of MonadReader
instance for "(->)" and of
Applicative
programming style with <$>
and <*>
.
Note: fromJSValueM
is deprecated, in future fromJSValue
will be
generalized to work in any MonadReader
JSValue
.
Nothing
fromJSValue :: JSValue -> Maybe a Source #
fromJSValueM :: (JSValueContainer c, MonadReader c m) => m (Maybe a) Source #
Instances
class FromJSValueWithUpdate a where Source #
Structures that can be parsed
from JSON, fields absent in the
JSON will be filled in using (optional) original structure.
By convention JSON null should be treated as a request to reset structure element to default value.
Nothing
fromJSValueWithUpdate :: Maybe a -> JSValue -> Maybe a Source #
fromJSValueWithUpdateM :: (JSValueContainer c, MonadReader c m) => Maybe a -> m (Maybe a) Source #
class MatchWithJSValue a where Source #
Structures that can be matched with JSValue
Nothing
matchesWithJSValue :: a -> JSValue -> Bool Source #
matchesWithJSValueM :: (JSValueContainer c, MonadReader c m) => a -> m Bool Source #
Data Extraction
jsValueField :: (JSValueContainer c, MonadReader c m, FromJSValue a) => String -> m (Maybe (Maybe a)) Source #
Reading the value that is on some field. Returns Nothing
if
JSON is not an object or field is present but cannot be parsed,
'Just Nothing' if absent, and 'Just (Just a)' otherwise
fromJSValueField :: (JSValueContainer c, MonadReader c m, FromJSValue a) => String -> m (Maybe a) Source #
Reading the value that is on a field. Semantics are a bit involved, example GHCi session should clarify:
Prelude> :set -XNoMonomorphismRestriction Prelude> let x = withJSValue (JSObject (toJSObject [("key",JSString $ toJSString "value")])) Prelude> x (fromJSValueField "key") :: IO (Maybe Int) Nothing Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe Int)) Just Nothing Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe (Maybe Int))) Just (Just Nothing) Prelude> x (fromJSValueField "key") :: IO (Maybe String) Just "value" Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe String)) Just (Just "value") Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe (Maybe String))) Just (Just (Just "value")) Prelude> let x = withJSValue (JSArray []) Prelude> x (fromJSValueField "key") :: IO (Maybe String) Nothing Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe String)) Nothing Prelude> x (fromJSValueField "key") :: IO (Maybe (Maybe (Maybe String))) Nothing
fromJSValueFieldBase64 :: (JSValueContainer c, MonadReader c m) => String -> m (Maybe ByteString) Source #
Version of fromJSValueField
for Base64 encoded data to avoid
memory leak.
fromJSValueFieldCustom :: (JSValueContainer c, MonadReader c m) => String -> m (Maybe a) -> m (Maybe a) Source #
Generalization of fromJSValueField
. Does not use FromJSValue
instances.
fromJSValueCustomMany :: (JSValueContainer c, MonadReader c m) => m (Maybe a) -> m (Maybe [a]) Source #
Runs parser on each element of underlaying json. Returns Just iff JSON is array.
fromJSValueCustomList :: (JSValueContainer c, MonadReader c m) => [m (Maybe a)] -> m (Maybe [a]) Source #
Generalization of fromJSValueCustomMany
, where each element of
array can have different parser.
fromJSValueManyWithUpdate :: (JSValueContainer c, MonadReader c m, FromJSValueWithUpdate a, MatchWithJSValue a) => [a] -> m (Maybe [a]) Source #
Runs parser on each element of underlying json. Returns Just
iff
JSON is an array.
Note: This method has quadratic complexity. It is better to write less general matching algorithms that use Maps.
Running
withJSValue :: Monad m => JSValue -> ReaderT JSValue m a -> m a Source #
Simple runner. Example:
let (v :: MyStruct) = runIdentity $ withJSValue js (fromJSValueM)
or inline:
let z = runIdentity $ withJSValue js $ do a <- fromJSValueField "a" b <- fromJSValueField "b" c <- fromJSValueField "c" return ((,,) <$> a <*> b <*> <*> c)
or using the monad transformer:
z <- withJSValue js $ do a <- fromJSValueField "a" b <- fromJSValueField "b" c <- fromJSValueField "c" return ((,,) <$> a <*> b <*> c)