Copyright | (c) Marek Fajkus |
---|---|
License | BSD3 |
Maintainer | marek.faj@gmail.com |
Safe Haskell | None |
Language | Haskell2010 |
Functions in this module serve as an alternative
ToJSON
type class. This allows to define for mapping
from data type into multiple JSON representations.
type level wrapping.
There are two way of defining such encoder:
- Using simple function
a -> Value
which doesn't require this library - Using this library as DSL together with
Contravariant
Synopsis
- newtype Encoder a = Encoder (a -> Value)
- auto :: ToJSON a => Encoder a
- run :: Encoder a -> a -> Value
- type KeyValueEncoder a = a -> Pair
- object :: [KeyValueEncoder a] -> Encoder a
- field :: Text -> Encoder b -> (a -> b) -> KeyValueEncoder a
- type KeyValueEncoder' a = a -> [Pair]
- object' :: KeyValueEncoder' a -> Encoder a
- field' :: Text -> Encoder a -> a -> (Text, Value)
- list :: Encoder a -> Encoder [a]
- vector :: Encoder a -> Encoder (Vector a)
- jsonArray :: [Encoder a] -> Encoder a
- void :: Encoder Void
- unit :: Encoder ()
- bool :: Encoder Bool
- int :: Encoder Int
- integer :: Encoder Integer
- int8 :: Encoder Int8
- int16 :: Encoder Int16
- int32 :: Encoder Int32
- int64 :: Encoder Int64
- word :: Encoder Word
- word8 :: Encoder Word8
- word16 :: Encoder Word16
- word32 :: Encoder Word32
- word64 :: Encoder Word64
- natural :: Encoder Natural
- float :: Encoder Float
- double :: Encoder Double
- scientific :: Encoder Scientific
- char :: Encoder Char
- text :: Encoder Text
- string :: Encoder String
- uuid :: Encoder UUID
- version :: Encoder Version
- zonedTime :: Encoder ZonedTime
- localTime :: Encoder LocalTime
- timeOfDay :: Encoder TimeOfDay
- utcTime :: Encoder UTCTime
- day :: Encoder Day
- dayOfWeek :: Encoder DayOfWeek
- encode :: Encoder a -> a -> ByteString
- toEncoding :: Encoder a -> a -> Encoding
Importing
This module as meant to be import as qualified
import Data.Aeson.Combinators.Encode as Encode
Aleternative to using Encode
Combinators
Be aware than in most cause you won't need to use this module.
you can utilize Aeson's Value
type and it's instance of ToJSON
directly.
>>>
import qualified Data.Aeson as Aeson
>>>
import Data.Aeson ((.=))
>>>
data Object = Object { tag :: String, id :: Int }
Define custom encoding function:
>>>
:{
encodeObject :: Object -> Value encodeObject (Object tag id) = Aeson.object ["tag" .= tag, "id" .= id] :}
>>>
Aeson.encode (encodeObject (Object "foo" 42))
"{\"tag\":\"foo\",\"id\":42}"
Example Usage
>>>
:set -XOverloadedStrings
>>>
:set -XDeriveGeneric
First lets define some type
>>>
:{
data Person = Person { name :: String , age :: Int } deriving (Show, Eq) :}
And first encoder for this type:
>>>
:{
personEncoder :: Encoder Person personEncoder = object [ field "name" string name , field "age" int age ] :}
We can use this Encoder
to encode value into JSON:
>>>
encode personEncoder (Person "Jane" 42)
"{\"age\":42,\"name\":\"Jane\"}"
Now we can use Contravariant
to manipulate our encoder.
Our type might be wrap in some rither type like this one:
>>>
import Data.Functor.Contravariant
>>>
data Surrounding = S Person Bool
But we still want to be able to encode it:
>>>
:{
surroundingEncoder :: Encoder Surrounding surroundingEncoder = contramap (\(S person _) -> person) personEncoder :}
Encoder
Value describing encoding of a
into a JSON Value
.
This is essentially just a wrapper around function that
should be applied later.
Covariant to map function over input
Given:
>>>
:{
data Person = Person { name :: String , age :: Int } deriving (Show, Eq) :}
>>>
:{
personEncoder :: Encoder Person personEncoder = object [ field "name" string name , field "age" int age ] :}
We can extract person from any pair:
>>>
:{
-- Using personEncoder definition from example above pairEncoder2 :: Encoder (Person, a) pairEncoder2 = contramap fst personEncoder :}
>>>
encode pairEncoder2 (Person "Jane" 42, Nothing)
"{\"age\":42,\"name\":\"Jane\"}"
Divisible and Decidable
Some of you might know library covariant
and ask what is a support for
other covariant typeclasses.
It's not possible to define lawful Divisble instance for JSON Value
and by extension it's not possible to define Decidable either.
While it is posible to provide somewhat useful unlawful instances for these this
library opts to not to do that.
run :: Encoder a -> a -> Value Source #
Run Encoder
given a value. this is essentially just a function application.
Object Encoding
There are two alternative ways of defining Object encodings.
Both provide "eqvivalent" types and functions with consistent naming.
Variants without and with '
suffix are meant to be used together.
type KeyValueEncoder a = a -> Pair Source #
Object Encoder
>>>
:{
data Object = Object { name :: Text , age :: Int } deriving (Show, Eq) :}
>>>
:{
objectEncoder :: Encoder Object objectEncoder = object [ field "name" text name , field "age" int age ] :}
>>>
encode objectEncoder $ Object "Joe" 30
"{\"age\":30,\"name\":\"Joe\"}"
object :: [KeyValueEncoder a] -> Encoder a Source #
Object combinators
Alternative Object Encoding
type KeyValueEncoder' a = a -> [Pair] Source #
Object Encoder (alternative)
>>>
:set -XRecordWildCards
>>>
:{
data Object = Object { name :: Text , age :: Int } deriving (Show, Eq) :}
>>>
:{
objectEncoder' :: Encoder Object objectEncoder' = object' $ \Object{..} -> [ field' "name" text name , field' "age" int age ] :}
>>>
encode objectEncoder' $ Object "Joe" 30
"{\"age\":30,\"name\":\"Joe\"}"
object' :: KeyValueEncoder' a -> Encoder a Source #
Object combinators (alternative)
Collections
Encoding Primitive Values
Void, Unit, Bool
Encode any JSON value to Void
value
which is impossible to construct.
This Encoder is guarenteed to fail.
Integers (and Natural)
natural :: Encoder Natural Source #
Encode JSON number to GHC's Natural
(non negative)
This function requires base
>= 4.8.0
Floating Points
scientific :: Encoder Scientific Source #
Encode JSON number to arbitrary precision Scientific
Strings
Encoding Time
zonedTime :: Encoder ZonedTime Source #
Encode JSON string to ZonedTime
using Aeson's instance implementation.
Supported string formats:
YYYY-MM-DD HH:MM Z YYYY-MM-DD HH:MM:SS Z YYYY-MM-DD HH:MM:SS.SSS Z
The first space may instead be a T, and the second space is optional. The Z represents UTC. The Z may be replaced with a time zone offset of the form +0000 or -08:00, where the first two digits are hours, the : is optional and the second two digits (also optional) are minutes.
localTime :: Encoder LocalTime Source #
Encode JSON string to LocalTime
using Aeson's instance implementation.
timeOfDay :: Encoder TimeOfDay Source #
Encode JSON string to TimeOfDay
using Aeson's instance implementation.
utcTime :: Encoder UTCTime Source #
Encode JSON string to UTCTime
using Aesons's instance implementation
dayOfWeek :: Encoder DayOfWeek Source #
Encode JSON string to DayOfWeek
using Aesons's instance implementation
This function requires 'time-compat' >= 1.9.2
Evaluating Encoders
encode :: Encoder a -> a -> ByteString Source #
Encode value into (Lazy) ByteString
toEncoding :: Encoder a -> a -> Encoding Source #
Convert value to encoding