Yesod.Core.Json

yesod-core-1.4.24: Creation of type-safe, RESTful web applications.

Safe Haskell | None
Language | Haskell98

Yesod.Core.Json

Contents

- Convert from a JSON value
- Convert to a JSON value
- Produce JSON values
- Convenience functions

Synopsis

- defaultLayoutJson :: (Yesod site, ToJSON a) => WidgetT site IO () -> HandlerT site IO a -> HandlerT site IO TypedContent
- jsonToRepJson :: (Monad m, ToJSON a) => a -> m Value
- returnJson :: (Monad m, ToJSON a) => a -> m Value
- returnJsonEncoding :: (Monad m, ToJSON a) => a -> m Encoding
- provideJson :: (Monad m, ToJSON a) => a -> Writer (Endo [ProvidedRep m]) ()
- parseJsonBody :: (MonadHandler m, FromJSON a) => m (Result a)
- parseJsonBody_ :: (MonadHandler m, FromJSON a) => m a
- requireJsonBody :: (MonadHandler m, FromJSON a) => m a
- data Value :: *
  - = Object ~Object
  - | Array ~Array
  - | String ~Text
  - | Number ~Scientific
  - | Bool ~Bool
  - | Null
- class ToJSON a where
  - toJSON :: a -> Value
  - toEncoding :: a -> Encoding
- class FromJSON a where
  - parseJSON :: Value -> Parser a
- array :: ToJSON a => [a] -> Value
- object :: [Pair] -> Value
- (.=) :: KeyValue kv => forall v. ToJSON v => Text -> v -> kv
- (.:) :: FromJSON a => Object -> Text -> Parser a
- jsonOrRedirect :: (MonadHandler m, ToJSON a) => Route (HandlerSite m) -> a -> m Value
- jsonEncodingOrRedirect :: (MonadHandler m, ToJSON a) => Route (HandlerSite m) -> a -> m Encoding
- acceptsJson :: MonadHandler m => m Bool

# Convert from a JSON value

defaultLayoutJson #

Arguments

:: (Yesod site, ToJSON a) |
=> WidgetT site IO () | HTML
-> HandlerT site IO a | JSON
-> HandlerT site IO TypedContent |

Provide both an HTML and JSON representation for a piece of data, using the default layout for the HTML output (`defaultLayout`).

Since: 0.3.0

jsonToRepJson :: (Monad m, ToJSON a) => a -> m Value #

Deprecated: Use returnJson instead

Wraps a data type in a `RepJson`. The data type must support conversion to JSON via `ToJSON`.

Since: 0.3.0

returnJson :: (Monad m, ToJSON a) => a -> m Value #

Convert a value to a JSON representation via aeson's `toJSON` function.

Since: 1.2.1

returnJsonEncoding :: (Monad m, ToJSON a) => a -> m Encoding #

Convert a value to a JSON representation via aeson's `toEncoding` function.

Since: 1.4.21

provideJson :: (Monad m, ToJSON a) => a -> Writer (Endo [ProvidedRep m]) () #

Provide a JSON representation for usage with `selectReps`, using aeson's `toJSON` (aeson >= 0.11: `toEncoding`) function to perform the conversion.

Since: 1.2.1

# Convert to a JSON value

parseJsonBody :: (MonadHandler m, FromJSON a) => m (Result a) #

Parse the request body to a data type as a JSON value. The data type must support conversion from JSON via `FromJSON`. If you want the raw JSON value, just ask for a ``Result` `Value``.

Note that this function will consume the request body. As such, calling it twice will result in a parse error on the second call, since the request body will no longer be available.

Since: 0.3.0

parseJsonBody_ :: (MonadHandler m, FromJSON a) => m a #

Deprecated: Use requireJsonBody instead

Same as `parseJsonBody`, but return an invalid args response on a parse error.

requireJsonBody :: (MonadHandler m, FromJSON a) => m a #

Same as `parseJsonBody`, but return an invalid args response on a parse error.

# Produce JSON values

data Value :: * #

A JSON value represented as a Haskell value.

Constructors

Object ~Object |
Array ~Array |
String ~Text |
Number ~Scientific |
Bool ~Bool |
Null |

Instances

Eq Value |
Methods (==) :: Value -> Value -> Bool # (/=) :: Value -> Value -> Bool #
Data Value |
Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Value -> c Value # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Value # toConstr :: Value -> Constr # dataTypeOf :: Value -> DataType # dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c Value) # dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Value) # gmapT :: (forall b. Data b => b -> b) -> Value -> Value # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Value -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Value -> r # gmapQ :: (forall d. Data d => d -> u) -> Value -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Value -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Value -> m Value # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Value -> m Value # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Value -> m Value #
Read Value |
Methods readsPrec :: Int -> ReadS Value # readList :: ReadS [Value] # readPrec :: ReadPrec Value # readListPrec :: ReadPrec [Value] #
Show Value |
Methods showsPrec :: Int -> Value -> ShowS # show :: Value -> String # showList :: [Value] -> ShowS #
IsString Value |
Methods fromString :: String -> Value #
Lift Value |
Methods lift :: Value -> Q Exp #
NFData Value |
Methods rnf :: Value -> () #
Hashable Value |
Methods hashWithSalt :: Int -> Value -> Int # hash :: Value -> Int #
ToJavascript Value |
Methods toJavascript :: Value -> Javascript #
ToTypedContent Value # |
Methods toTypedContent :: Value -> TypedContent #
HasContentType Value # |
Methods getContentType :: Monad m => m Value -> ContentType #
ToContent Value # |
Methods toContent :: Value -> Content #

class ToJSON a where #

A type that can be converted to JSON.

An example type and instance:

    -- Allow ourselves to write Text literals.
    {-# LANGUAGE OverloadedStrings #-}

    data Coord = Coord { x :: Double, y :: Double }

    instance ToJSON Coord where
      toJSON (Coord x y) = object ["x" .= x, "y" .= y]

      toEncoding (Coord x y) = pairs ("x" .= x <> "y" .= y)

Instead of manually writing your `ToJSON` instance, there are two options to do it automatically:

- Data.Aeson.TH provides Template Haskell functions which will derive an instance at compile time. The generated instance is optimized for your type so will probably be more efficient than the following two options:
- The compiler can provide a default generic implementation for `toJSON`.

To use the second, simply add a `deriving `Generic`` clause to your datatype and declare a `ToJSON` instance for your datatype without giving definitions for `toJSON` or `toEncoding`.

For example, the previous example can be simplified to a more minimal instance:

    {-# LANGUAGE DeriveGeneric #-}

    import GHC.Generics

    data Coord = Coord { x :: Double, y :: Double } deriving Generic

    instance ToJSON Coord where
        toEncoding = genericToEncoding defaultOptions

Why do we provide an implementation for `toEncoding` here? The `toEncoding` function is a relatively new addition to this class. To allow users of older versions of this library to upgrade without having to edit all of their instances or encounter surprising incompatibilities, the default implementation of `toEncoding` uses `toJSON`. This produces correct results, but since it performs an intermediate conversion to a `Value`, it will be less efficient than directly emitting an `Encoding`. Our one-liner definition of `toEncoding` above bypasses the intermediate `Value`.

If `DefaultSignatures` doesn't give exactly the results you want, you can customize the generic encoding with only a tiny amount of effort, using `genericToJSON` and `genericToEncoding` with your preferred `Options`:

    instance ToJSON Coord where
        toJSON     = genericToJSON defaultOptions
        toEncoding = genericToEncoding defaultOptions

Minimal complete definition

Nothing

class FromJSON a where #

A type that can be converted from JSON, with the possibility of failure.

In many cases, you can get the compiler to generate parsing code for you (see below). To begin, let's cover writing an instance by hand.

There are various reasons a conversion could fail. For example, an `Object` could be missing a required key, an `Array` could be of the wrong size, or a value could be of an incompatible type.

The basic ways to signal a failed conversion are as follows:

- `empty` and `mzero` work, but are terse and uninformative
- `fail` yields a custom error message
- `typeMismatch` produces an informative message for cases when the value encountered is not of the expected type

An example type and instance:

    -- Allow ourselves to write Text literals.
    {-# LANGUAGE OverloadedStrings #-}

    data Coord = Coord { x :: Double, y :: Double }

    instance FromJSON Coord where
      parseJSON (Object v) = Coord    <$>
                             v .: "x" <*>
                             v .: "y"

      -- We do not expect a non-Object value here.
      -- We could use mzero to fail, but typeMismatch
      -- gives a much more informative error message.
      parseJSON invalid    = typeMismatch "Coord" invalid

Instead of manually writing your `FromJSON` instance, there are two options to do it automatically:

- Data.Aeson.TH provides Template Haskell functions which will derive an instance at compile time. The generated instance is optimized for your type so will probably be more efficient than the following two options:
- The compiler can provide a default generic implementation for `parseJSON`.

To use the second, simply add a `deriving `Generic`` clause to your datatype and declare a `FromJSON` instance for your datatype without giving a definition for `parseJSON`.

For example, the previous example can be simplified to just:

    {-# LANGUAGE DeriveGeneric #-}

    import GHC.Generics

    data Coord = Coord { x :: Double, y :: Double } deriving Generic

    instance FromJSON Coord

If `DefaultSignatures` doesn't give exactly the results you want, you can customize the generic decoding with only a tiny amount of effort, using `genericParseJSON` with your preferred `Options`:

    instance FromJSON Coord where
        parseJSON = genericParseJSON defaultOptions

Minimal complete definition

Nothing

array :: ToJSON a => [a] -> Value #

Convert a list of values to an `Array`.

object :: [Pair] -> Value #

Create a `Value` from a list of name/value `Pair`s. If duplicate keys arise, earlier keys and their associated values win.

(.=) :: KeyValue kv => forall v. ToJSON v => Text -> v -> kv #

(.:) :: FromJSON a => Object -> Text -> Parser a #

Retrieve the value associated with the given key of an `Object`. The result is `empty` if the key is not present or the value cannot be converted to the desired type.

This accessor is appropriate if the key and value must be present in an object for it to be valid. If the key and value are optional, use `.:?` instead.

# Convenience functions

jsonOrRedirect #

Arguments

:: (MonadHandler m, ToJSON a) |
=> Route (HandlerSite m) | Redirect target
-> a | Data to send via JSON
-> m Value |

jsonOrRedirect simplifies the scenario where a POST handler sends a different response based on Accept headers:

1. 200 with JSON data if the client prefers `application/json` (e.g. AJAX, see `acceptsJSON`).
2. 3xx otherwise, following the PRG pattern.

jsonEncodingOrRedirect #

Arguments

:: (MonadHandler m, ToJSON a) |
=> Route (HandlerSite m) | Redirect target
-> a | Data to send via JSON
-> m Encoding |

jsonEncodingOrRedirect simplifies the scenario where a POST handler sends a different response based on Accept headers:

1. 200 with JSON data if the client prefers `application/json` (e.g. AJAX, see `acceptsJSON`).
2. 3xx otherwise, following the PRG pattern. @since 1.4.21

acceptsJson :: MonadHandler m => m Bool #

Returns `True` if the client prefers `application/json` as indicated by the `Accept` HTTP header.