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

A JSON value represented as a Haskell value.

Constructors

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

Instances

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

data Encoding

An encoding of a JSON value.

Instances

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

fromEncoding :: Encoding -> Builder

Acquire the underlying bytestring builder.

data Series

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

Instances

Monoid Series |

type Array = Vector Value

A JSON "array" (sequence).

emptyArray :: Value

The empty array.

type Pair = (Text, Value)

A key/value pair for an `Object`.

type Object = HashMap Text Value

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

emptyObject :: Value

The empty object.

# Convenience types and functions

newtype DotNetTime

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 |
Ord DotNetTime |
Read DotNetTime |
Show DotNetTime |
FormatTime DotNetTime |

typeMismatch

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

A JSON parser.

Instances

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

data Result a

The result of running a `Parser`.

Constructors

Error String |
Success a |

Instances

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

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

Methods

parseJSON :: Value -> Parser a

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

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

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

Run a `Parser`.

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

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

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

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

toJSON

Methods

toJSON :: a -> Value

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

toEncoding :: a -> Encoding

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

A key-value pair for encoding a JSON object.

Methods

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

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

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

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

Methods

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

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

class GToJSON f where

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

Methods

gToJSON :: Options -> f a -> Value

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

gToEncoding :: Options -> f a -> Encoding

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

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

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

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

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

`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

`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

`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

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

`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

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

pairs :: Series -> Encoding

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

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

Encode a `Foldable` as a JSON array.

(.:) :: 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.

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

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

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

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

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 |

data SumEncoding

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 |
Show SumEncoding |

camelTo :: Char -> String -> String

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

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

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

defaultOptions :: Options

Default encoding `Options`:

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

defaultTaggedObject :: SumEncoding

Default `TaggedObject` `SumEncoding` options:

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