aeson-0.10.0.0: Fast JSON parsing and encoding

Copyright | (c) 2011-2015 Bryan O'Sullivan (c) 2011 MailRank, Inc.
License | Apache
Maintainer | Bryan O'Sullivan <bos@serpentine.com>
Stability | experimental
Portability | portable
Safe Haskell | None
Language | Haskell98

Data.Aeson.Types

Contents

- Core JSON types
- Convenience types and functions
- Type conversion
  - Generic JSON classes
- Inspecting ``Value`s`
- Generic and TH encoding configuration

Description

Types for working with JSON data.

Synopsis

- data Value
  - = Object !Object
  - | Array !Array
  - | String !Text
  - | Number !Scientific
  - | Bool !Bool
  - | Null
- data Encoding
- fromEncoding :: Encoding -> Builder
- data Series
- type Array = Vector Value
- emptyArray :: Value
- type Pair = (Text, Value)
- type Object = HashMap Text Value
- emptyObject :: Value
- newtype DotNetTime = DotNetTime {
  - fromDotNetTime :: UTCTime
  }
- typeMismatch :: String -> Value -> Parser a
- data Parser a
- data Result a
  - = Error String
  - | Success a
- class FromJSON a where
  - parseJSON :: Value -> Parser a
- fromJSON :: FromJSON a => Value -> Result a
- parse :: (a -> Parser b) -> a -> Result b
- parseEither :: (a -> Parser b) -> a -> Either String b
- parseMaybe :: (a -> Parser b) -> a -> Maybe b
- class ToJSON a where
  - toJSON :: a -> Value
  - toEncoding :: a -> Encoding
- class KeyValue kv where
  - (.=) :: ToJSON v => Text -> v -> kv
- modifyFailure :: (String -> String) -> Parser a -> Parser a
- class GFromJSON f where
  - gParseJSON :: Options -> Value -> Parser (f a)
- class GToJSON f where
  - gToJSON :: Options -> f a -> Value
  - gToEncoding :: Options -> f a -> Encoding
- genericToJSON :: (Generic a, GToJSON (Rep a)) => Options -> a -> Value
- genericToEncoding :: (Generic a, GToJSON (Rep a)) => Options -> a -> Encoding
- genericParseJSON :: (Generic a, GFromJSON (Rep a)) => Options -> Value -> Parser a
- withObject :: String -> (Object -> Parser a) -> Value -> Parser a
- withText :: String -> (Text -> Parser a) -> Value -> Parser a
- withArray :: String -> (Array -> Parser a) -> Value -> Parser a
- withNumber :: String -> (Number -> Parser a) -> Value -> Parser a
- withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a
- withBool :: String -> (Bool -> Parser a) -> Value -> Parser a
- pairs :: Series -> Encoding
- foldable :: (Foldable t, ToJSON a) => t a -> Encoding
- (.:) :: FromJSON a => Object -> Text -> Parser a
- (.:?) :: FromJSON a => Object -> Text -> Parser (Maybe a)
- (.!=) :: Parser (Maybe a) -> a -> Parser a
- object :: [Pair] -> Value
- data Options = Options {
  - fieldLabelModifier :: String -> String
  - constructorTagModifier :: String -> String
  - allNullaryToStringTag :: Bool
  - omitNothingFields :: Bool
  - sumEncoding :: SumEncoding
  - unwrapUnaryRecords :: Bool
  }
- data SumEncoding
  - = TaggedObject {
    - tagFieldName :: String
    - contentsFieldName :: String
    }
  - | ObjectWithSingleField
  - | TwoElemArray
- camelTo :: Char -> String -> String
- camelTo2 :: Char -> String -> String
- defaultOptions :: Options
- defaultTaggedObject :: SumEncoding

# Core JSON types

data Value Source

A JSON value represented as a Haskell value.

Constructors

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

Instances

Eq Value Source |
Data Value Source |
Read Value Source |
Show Value Source |
IsString Value Source |
NFData Value Source |
Hashable Value Source |

data Encoding Source

An encoding of a JSON value.

Instances

Eq Encoding Source |
Ord Encoding Source |
Show Encoding Source |
Monoid Encoding Source |

fromEncoding :: Encoding -> Builder Source

Acquire the underlying bytestring builder.

data Series Source

A series of values that, when encoded, should be separated by commas.

Instances

Monoid Series Source |

type Array = Vector Value Source

A JSON "array" (sequence).

emptyArray :: Value Source

The empty array.

type Pair = (Text, Value) Source

A key/value pair for an `Object`.

type Object = HashMap Text Value Source

A JSON "object" (key/value map).

emptyObject :: Value Source

The empty object.

# Convenience types and functions

newtype DotNetTime Source

A newtype wrapper for `UTCTime` that uses the same non-standard serialization format as Microsoft .NET, whose System.DateTime type is by default serialized to JSON as in the following example:

    /Date(1302547608878)/

The number represents milliseconds since the Unix epoch.

Constructors

DotNetTime |

Fields

fromDotNetTime :: UTCTime

  Acquire the underlying value.

Instances

Eq DotNetTime Source |
Ord DotNetTime Source |
Read DotNetTime Source |
Show DotNetTime Source |
FormatTime DotNetTime Source |

typeMismatch Source

Arguments

:: String | The name of the type you are trying to parse.
-> Value | The actual value encountered.
-> Parser a |

Fail parsing due to a type mismatch, with a descriptive message.

Example usage:

    instance FromJSON Coord where
      parseJSON (Object v) = {- type matches, life is good -}
      parseJSON wat        = typeMismatch "Coord" wat

# Type conversion

data Parser a Source

A JSON parser.

Instances

Monad Parser Source |
Functor Parser Source |
Applicative Parser Source |
Alternative Parser Source |
MonadPlus Parser Source |
Monoid (Parser a) Source |

data Result a Source

The result of running a `Parser`.

Constructors

Error String |
Success a |

Instances

Monad Result Source |
Functor Result Source |
Applicative Result Source |
Foldable Result Source |
Traversable Result Source |
Alternative Result Source |
MonadPlus Result Source |
Eq a => Eq (Result a) Source |
Show a => Show (Result a) Source |
Monoid (Result a) Source |
NFData a => NFData (Result a) Source |

class FromJSON a where Source

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

Methods

parseJSON :: Value -> Parser a Source

fromJSON :: FromJSON a => Value -> Result a Source

Convert a value from JSON, failing if the types do not match.

parse :: (a -> Parser b) -> a -> Result b Source

Run a `Parser`.

parseEither :: (a -> Parser b) -> a -> Either String b Source

Run a `Parser` with an `Either` result type. If the parse fails, the `Left` payload will contain an error message.

parseMaybe :: (a -> Parser b) -> a -> Maybe b Source

Run a `Parser` with a `Maybe` result type.

class ToJSON a where Source

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

toJSON

Methods

toJSON :: a -> Value Source

Convert a Haskell value to a JSON-friendly intermediate type.

toEncoding :: a -> Encoding Source

Encode a Haskell value as JSON.

The default implementation of this method creates an intermediate `Value` using `toJSON`. This provides source-level compatibility for people upgrading from older versions of this library, but obviously offers no performance advantage.

To benefit from direct encoding, you must provide an implementation for this method. The easiest way to do so is by having your types implement `Generic` using the `DeriveGeneric` extension, and then have GHC generate a method body as follows.

    instance ToJSON Coord where
        toEncoding = genericToEncoding defaultOptions

class KeyValue kv where Source

A key-value pair for encoding a JSON object.

Methods

(.=) :: ToJSON v => Text -> v -> kv infixr 8 Source

modifyFailure :: (String -> String) -> Parser a -> Parser a Source

If the inner `Parser` failed, modify the failure message using the provided function. This allows you to create more descriptive error messages. For example:

    parseJSON (Object o) = modifyFailure
        ("Parsing of the Foo value failed: " ++)
        (Foo <$> o .: "someField")

Since 0.6.2.0

## Generic JSON classes

class GFromJSON f where Source

Class of generic representation types (`Rep`) that can be converted from JSON.

Methods

gParseJSON :: Options -> Value -> Parser (f a) Source

This method (applied to `defaultOptions`) is used as the default generic implementation of `parseJSON`.

class GToJSON f where Source

Class of generic representation types (`Rep`) that can be converted to JSON.

Methods

gToJSON :: Options -> f a -> Value Source

This method (applied to `defaultOptions`) is used as the default generic implementation of `toJSON`.

gToEncoding :: Options -> f a -> Encoding Source

This method (applied to `defaultOptions`) can be used as the default generic implementation of `toEncoding`.

genericToJSON :: (Generic a, GToJSON (Rep a)) => Options -> a -> Value Source

A configurable generic JSON creator. This function applied to `defaultOptions` is used as the default for `toJSON` when the type is an instance of `Generic`.

genericToEncoding :: (Generic a, GToJSON (Rep a)) => Options -> a -> Encoding Source

A configurable generic JSON encoder. This function applied to `defaultOptions` is used as the default for `toEncoding` when the type is an instance of `Generic`.

genericParseJSON :: (Generic a, GFromJSON (Rep a)) => Options -> Value -> Parser a Source

A configurable generic JSON decoder. This function applied to `defaultOptions` is used as the default for `parseJSON` when the type is an instance of `Generic`.

# Inspecting ``Value`s`

withObject :: String -> (Object -> Parser a) -> Value -> Parser a Source

`withObject expected f value` applies `f` to the `Object` when `value` is an `Object` and fails using ``typeMismatch` expected` otherwise.

withText :: String -> (Text -> Parser a) -> Value -> Parser a Source

`withText expected f value` applies `f` to the `Text` when `value` is a `String` and fails using ``typeMismatch` expected` otherwise.

withArray :: String -> (Array -> Parser a) -> Value -> Parser a Source

`withArray expected f value` applies `f` to the `Array` when `value` is an `Array` and fails using ``typeMismatch` expected` otherwise.

withNumber :: String -> (Number -> Parser a) -> Value -> Parser a Source

Deprecated: Use withScientific instead

`withNumber expected f value` applies `f` to the `Number` when `value` is a `Number`. and fails using ``typeMismatch` expected` otherwise.

withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a Source

`withScientific expected f value` applies `f` to the `Scientific` number when `value` is a `Number`. and fails using ``typeMismatch` expected` otherwise.

withBool :: String -> (Bool -> Parser a) -> Value -> Parser a Source

`withBool expected f value` applies `f` to the `Bool` when `value` is a `Bool` and fails using ``typeMismatch` expected` otherwise.

pairs :: Series -> Encoding Source

Encode a series of key/value pairs, separated by commas.

foldable :: (Foldable t, ToJSON a) => t a -> Encoding Source

Encode a `Foldable` as a JSON array.

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

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.

(.:?) :: FromJSON a => Object -> Text -> Parser (Maybe a) Source

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

This accessor is most useful if the key and value can be absent from an object without affecting its validity. If the key and value are mandatory, use '(.:)' instead.

(.!=) :: Parser (Maybe a) -> a -> Parser a Source

Helper for use in combination with `.:?` to provide default values for optional JSON object fields.

This combinator is most useful if the key and value can be absent from an object without affecting its validity and we know a default value to assign in that case. If the key and value are mandatory, use '(.:)' instead.

Example usage:

     v1 <- o .:? "opt_field_with_dfl" .!= "default_val"
     v2 <- o .:  "mandatory_field"
     v3 <- o .:? "opt_field2"

object :: [Pair] -> Value Source

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

# Generic and TH encoding configuration

data Options Source

Options that specify how to encode/decode your datatype to/from JSON.

Constructors

Options |

Fields

fieldLabelModifier :: String -> String

  Function applied to field labels. Handy for removing common record prefixes for example.

constructorTagModifier :: String -> String

  Function applied to constructor tags which could be handy for lower-casing them for example.

allNullaryToStringTag :: Bool

  If `True` the constructors of a datatype, with all nullary constructors, will be encoded to just a string with the constructor tag. If `False` the encoding will always follow the `sumEncoding`.

omitNothingFields :: Bool

  If `True` record fields with a `Nothing` value will be omitted from the resulting object. If `False` the resulting object will include those fields mapping to `null`.

sumEncoding :: SumEncoding

  Specifies how to encode constructors of a sum datatype.

unwrapUnaryRecords :: Bool

  Hide the field name when a record constructor has only one field, like a newtype.

Instances

Show Options Source |

data SumEncoding Source

Specifies how to encode constructors of a sum datatype.

Constructors

TaggedObject

A constructor will be encoded to an object with a field `tagFieldName` which specifies the constructor tag (modified by the `constructorTagModifier`). If the constructor is a record the encoded record fields will be unpacked into this object. So make sure that your record doesn't have a field with the same label as the `tagFieldName`. Otherwise the tag gets overwritten by the encoded value of that field! If the constructor is not a record the encoded constructor contents will be stored under the `contentsFieldName` field.

Fields

tagFieldName :: String
contentsFieldName :: String

ObjectWithSingleField | A constructor will be encoded to an object with a single field named after the constructor tag (modified by the `constructorTagModifier`) which maps to the encoded contents of the constructor.
TwoElemArray | A constructor will be encoded to a 2-element array where the first element is the tag of the constructor (modified by the `constructorTagModifier`) and the second element the encoded contents of the constructor.

Instances

Eq SumEncoding Source |
Show SumEncoding Source |

camelTo :: Char -> String -> String Source

Deprecated: Use camelTo2 for better results

Converts from CamelCase to another lower case, interspersing the character between all capital letters and their previous entries, except those capital letters that appear together, like `API`.

For use by Aeson template haskell calls.

    camelTo '_' 'CamelCaseAPI' == "camel_case_api"

camelTo2 :: Char -> String -> String Source

Better version of `camelTo`. Example where it works better:

    camelTo '_' 'CamelAPICase' == "camel_apicase"
    camelTo2 '_' 'CamelAPICase' == "camel_api_case"

defaultOptions :: Options Source

Default encoding `Options`:

    Options
    { fieldLabelModifier      = id
    , constructorTagModifier  = id
    , allNullaryToStringTag   = True
    , omitNothingFields       = False
    , sumEncoding             = defaultTaggedObject
    }

defaultTaggedObject :: SumEncoding Source

Default `TaggedObject` `SumEncoding` options:

    defaultTaggedObject = TaggedObject
                          { tagFieldName      = "tag"
                          , contentsFieldName = "contents"
                          }