{-# LANGUAGE CPP                   #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
-- | Types and functions to encode your data types to 'Json'.
--
-- We will work through a basic example, using the following type:
--
-- @
-- data Person = Person
--   { _personName                    :: Text
--   , _personAge                     :: Int
--   , _personAddress                 :: Text
--   , _personFavouriteLotteryNumbers :: [Int]
--   }
--   deriving (Eq, Show)
-- @
--
-- To create an 'Waargonaut.Encode.Encoder' for our @Person@ record, we will encode it as a "map
-- like object", that is we have decided that there are no duplicate keys allowed. We can then use
-- the following functions to build up the structure we want:
--
-- @
-- mapLikeObj
--   :: ( AsJType Json ws a
--      , Semigroup ws         -- This library supports GHC 7.10.3 and 'Semigroup' wasn't a superclass of 'Monoid' then.
--      , Monoid ws
--      , Applicative f
--      )
--   => (i -> MapLikeObj ws a -> MapLikeObj ws a)
--   -> Encoder f i
-- @
--
-- And:
--
-- @
-- atKey'
--   :: ( At t
--      , IxValue t ~ Json
--      )
--   => Index t
--   -> Encoder' a
--   -> a
--   -> t
--   -> t
-- @
--
-- These types may seem pretty wild, but their usage is mundane. The 'Waargonaut.Encode.mapLikeObj'
-- function is used when we want to encode some particular type @i@ as a JSON object. In such a way
-- as to prevent duplicate keys from appearing. The 'Waargonaut.Encode.atKey'' function is designed
-- such that it can be composed with itself to build up an object with multiple keys.
--
-- @
-- import Waargonaut.Encode (Encoder)
-- import qualified Waargonaut.Encode as E
-- @
--
-- @
-- personEncoder :: Applicative f => Encoder f Person
-- personEncoder = E.mapLikeObj $ \\p ->
--   E.atKey' \"name\" E.text (_personName p) .
--   E.atKey' \"age\" E.int (_personAge p) .
--   E.atKey' \"address\" E.text (_personAddress p) .
--   E.atKey' \"numbers\" (E.list E.int) (_personFavouriteLotteryNumbers p)
-- @
--
-- The JSON RFC leaves the handling of duplicate keys on an object as a choice. It is up to the
-- implementor of a JSON handling package to decide what they will do. Waargonaut passes on this
-- choice to you. In both encoding and decoding, the handling of duplicate keys is up to you.
-- Waargonaut provides functionality to support /both/ use cases.
--
-- To then turn these values into JSON output:
--
-- @
-- simpleEncodeText         :: Applicative f => Encoder f a -> a -> f Text
-- simpleEncodeTextNoSpaces :: Applicative f => Encoder f a -> a -> f Text
--
-- simpleEncodeByteString         :: Applicative f => Encoder f a -> a -> f ByteString
-- simpleEncodeByteStringNoSpaces :: Applicative f => Encoder f a -> a -> f ByteString
-- @
--
-- Or
--
-- @
-- simplePureEncodeText         :: Encoder' a -> a -> Text
-- simplePureEncodeTextNoSpaces :: Encoder' a -> a -> Text
--
-- simplePureEncodeByteString         :: Encoder' a -> a -> ByteString
-- simplePureEncodeByteStringNoSpaces :: Encoder' a -> a -> ByteString
-- @
--
-- The latter functions specialise the @f@ to be 'Data.Functor.Identity'.
--
-- Then, like the use of the 'Waargonaut.Decode.Decoder' you select the 'Waargonaut.Encode.Encoder'
-- you wish to use and run it against a value of a matching type:
--
-- @
-- simplePureEncodeTextNoSpaces personEncoder (Person \"Krag\" 33 \"Red House 4, Three Neck Lane, Greentown.\" [86,3,32,42,73])
-- =
-- "{\"name\":\"Krag\",\"age\":88,\"address\":\"Red House 4, Three Neck Lane, Greentown.\",\"numbers\":[86,3,32,42,73]}"
-- @
--
module Waargonaut.Encode
  (
    -- * Encoder type
    Encoder
  , Encoder'
  , ObjEncoder
  , ObjEncoder'

    -- * Creation
  , encodeA
  , encodePureA
  , jsonEncoder
  , objEncoder

    -- * Runners
  , runPureEncoder
  , runEncoder
  , simpleEncodeWith
  , simplePureEncodeWith
  , simpleEncodeText
  , simpleEncodeTextNoSpaces
  , simpleEncodeByteString
  , simpleEncodeByteStringNoSpaces
  , simplePureEncodeText
  , simplePureEncodeTextNoSpaces
  , simplePureEncodeByteString
  , simplePureEncodeByteStringNoSpaces

    -- * Provided encoders
  , int
  , integral
  , scientific
  , bool
  , string
  , text
  , null
  , either
  , maybe
  , maybeOrNull
  , traversable
  , list
  , nonempty
  , mapToObj
  , json
  , prismE
  , asJson

    -- * Object encoder helpers
  , mapLikeObj
  , atKey
  , atOptKey
  , intAt
  , textAt
  , boolAt
  , traversableAt
  , listAt
  , nonemptyAt
  , encAt
  , keyValuesAsObj
  , onObj
  , keyValueTupleFoldable
  , extendObject
  , extendMapLikeObject
  , combineObjects

    -- * Encoders specialised to Identity
  , int'
  , integral'
  , scientific'
  , bool'
  , string'
  , text'
  , null'
  , either'
  , maybe'
  , maybeOrNull'
  , traversable'
  , nonempty'
  , list'
  , atKey'
  , atOptKey'
  , mapLikeObj'
  , mapToObj'
  , keyValuesAsObj'
  , json'
  , asJson'
  , onObj'
  , generaliseEncoder
  ) where


import           Control.Applicative                  (Applicative (..), (<$>))
import           Control.Category                     (id, (.))
import           Control.Lens                         (AReview, At, Index,
                                                       IxValue, Prism', at,
                                                       cons, review, ( # ),
                                                       (?~), _Empty, _Wrapped)
import qualified Control.Lens                         as L

import           Data.Foldable                        (Foldable, foldr, foldrM)
import           Data.Function                        (const, flip, ($), (&))
import           Data.Functor                         (Functor, fmap)
import           Data.Functor.Contravariant           ((>$<))
import           Data.Functor.Contravariant.Divisible (divide)
import           Data.Functor.Identity                (Identity (..))
import           Data.Traversable                     (Traversable, traverse)
import           Prelude                              (Bool, Int, Integral,
                                                       Monad, String,
                                                       fromIntegral, fst)

import           Data.Either                          (Either)
import qualified Data.Either                          as Either
import           Data.List.NonEmpty                   (NonEmpty)
import           Data.Maybe                           (Maybe)
import qualified Data.Maybe                           as Maybe
import           Data.Scientific                      (Scientific)

import           Data.Monoid                          (Monoid, mempty)
import           Data.Semigroup                       (Semigroup)

import           Data.Map                             (Map)
import qualified Data.Map                             as Map
import           Data.String                          (IsString)

import qualified Data.ByteString.Lazy                 as BL
import qualified Data.ByteString.Builder              as BB

import           Data.Text                            (Text)
import qualified Data.Text.Lazy                       as LT
import qualified Data.Text.Lazy.Builder               as TB

import           Waargonaut.Encode.Types              (Encoder, Encoder',
                                                       ObjEncoder, ObjEncoder',
                                                       finaliseEncoding,
                                                       generaliseEncoder,
                                                       initialEncoding,
                                                       jsonEncoder, objEncoder,
                                                       runEncoder,
                                                       runPureEncoder)

import           Waargonaut.Types                     (AsJType (..),
                                                       JAssoc (..), JObject,
                                                       Json, MapLikeObj (..),
                                                       WS, stringToJString,
                                                       toMapLikeObj,
                                                       _JNumberInt,
                                                       _JNumberScientific,
                                                       _JStringText)

import           Waargonaut.Encode.Builder            (textBuilder, bsBuilder,
                                                       waargonautBuilder)
import           Waargonaut.Encode.Builder.Types      (Builder)
import           Waargonaut.Encode.Builder.Whitespace (wsBuilder, wsRemover)


-- | Create an 'Encoder'' for @a@ by providing a function from 'a -> f Json'.
encodeA :: (a -> f Json) -> Encoder f a
encodeA :: (a -> f Json) -> Encoder f a
encodeA = (a -> f Json) -> Encoder f a
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
jsonEncoder

-- | As 'encodeA' but specialised to 'Identity' when the additional flexibility
-- isn't needed.
encodePureA :: (a -> Json) -> Encoder' a
encodePureA :: (a -> Json) -> Encoder' a
encodePureA a -> Json
f = (a -> Identity Json) -> Encoder' a
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA (Json -> Identity Json
forall a. a -> Identity a
Identity (Json -> Identity Json) -> (a -> Json) -> a -> Identity Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> Json
f)

-- | Encode an @a@ directly to some output text type using the provided
-- 'Waargonaut.Encode.Builder.Types.Builder' and 'Encoder'.
simpleEncodeWith
  :: ( Applicative f
     , Monoid b
     , IsString t
     )
  => Builder t b
  -> (b -> out)
  -> (Builder t b -> WS -> b)
  -> Encoder f a
  -> a
  -> f out
simpleEncodeWith :: Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder t b
builder b -> out
buildRunner Builder t b -> WS -> b
wsB Encoder f a
enc =
  (Json -> out) -> f Json -> f out
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b -> out
buildRunner (b -> out) -> (Json -> b) -> Json -> out
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Builder t b -> WS -> b) -> Builder t b -> Json -> b
forall t b.
(IsString t, Monoid b) =>
(Builder t b -> WS -> b) -> Builder t b -> Json -> b
waargonautBuilder Builder t b -> WS -> b
wsB Builder t b
builder) (f Json -> f out) -> (a -> f Json) -> a -> f out
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder f a
enc

-- | Encode an @a@ directly to a 'LT.Text' using the provided 'Encoder'.
simpleEncodeText
  :: Applicative f
  => Encoder f a
  -> a
  -> f LT.Text
simpleEncodeText :: Encoder f a -> a -> f Text
simpleEncodeText =
  Builder Text Builder
-> (Builder -> Text)
-> (Builder Text Builder -> WS -> Builder)
-> Encoder f a
-> a
-> f Text
forall (f :: * -> *) b t out a.
(Applicative f, Monoid b, IsString t) =>
Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder Text Builder
textBuilder Builder -> Text
TB.toLazyText Builder Text Builder -> WS -> Builder
forall b t. Monoid b => Builder t b -> WS -> b
wsBuilder

-- | Encode an @a@ directly to a 'LT.Text' using the provided 'Encoder'.
simpleEncodeTextNoSpaces
  :: Applicative f
  => Encoder f a
  -> a
  -> f LT.Text
simpleEncodeTextNoSpaces :: Encoder f a -> a -> f Text
simpleEncodeTextNoSpaces =
  Builder Text Builder
-> (Builder -> Text)
-> (Builder Text Builder -> WS -> Builder)
-> Encoder f a
-> a
-> f Text
forall (f :: * -> *) b t out a.
(Applicative f, Monoid b, IsString t) =>
Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder Text Builder
textBuilder Builder -> Text
TB.toLazyText Builder Text Builder -> WS -> Builder
forall b t. Monoid b => Builder t b -> WS -> b
wsRemover

-- | Encode an @a@ directly to a 'BL.ByteString' using the provided 'Encoder'.
simpleEncodeByteString
  :: Applicative f
  => Encoder f a
  -> a
  -> f BL.ByteString
simpleEncodeByteString :: Encoder f a -> a -> f ByteString
simpleEncodeByteString =
  Builder ByteString Builder
-> (Builder -> ByteString)
-> (Builder ByteString Builder -> WS -> Builder)
-> Encoder f a
-> a
-> f ByteString
forall (f :: * -> *) b t out a.
(Applicative f, Monoid b, IsString t) =>
Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder ByteString Builder
bsBuilder Builder -> ByteString
BB.toLazyByteString Builder ByteString Builder -> WS -> Builder
forall b t. Monoid b => Builder t b -> WS -> b
wsBuilder

-- | Encode an @a@ directly to a 'BL.ByteString' using the provided 'Encoder'.
simpleEncodeByteStringNoSpaces
  :: Applicative f
  => Encoder f a
  -> a
  -> f BL.ByteString
simpleEncodeByteStringNoSpaces :: Encoder f a -> a -> f ByteString
simpleEncodeByteStringNoSpaces =
  Builder ByteString Builder
-> (Builder -> ByteString)
-> (Builder ByteString Builder -> WS -> Builder)
-> Encoder f a
-> a
-> f ByteString
forall (f :: * -> *) b t out a.
(Applicative f, Monoid b, IsString t) =>
Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder ByteString Builder
bsBuilder Builder -> ByteString
BB.toLazyByteString Builder ByteString Builder -> WS -> Builder
forall b t. Monoid b => Builder t b -> WS -> b
wsRemover

-- | Encode an @a@ directly to a 'LT.Text' using the provided 'Encoder'.
simplePureEncodeWith
  :: ( Monoid b
     , IsString t
     )
  => Builder t b
  -> (b -> out)
  -> (Builder t b -> WS -> b)
  -> Encoder Identity a
  -> a
  -> out
simplePureEncodeWith :: Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder Identity a
-> a
-> out
simplePureEncodeWith Builder t b
builder b -> out
buildRunner Builder t b -> WS -> b
wsB Encoder Identity a
enc =
  Identity out -> out
forall a. Identity a -> a
runIdentity (Identity out -> out) -> (a -> Identity out) -> a -> out
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder Identity a
-> a
-> Identity out
forall (f :: * -> *) b t out a.
(Applicative f, Monoid b, IsString t) =>
Builder t b
-> (b -> out)
-> (Builder t b -> WS -> b)
-> Encoder f a
-> a
-> f out
simpleEncodeWith Builder t b
builder b -> out
buildRunner Builder t b -> WS -> b
wsB Encoder Identity a
enc

-- | As per 'simpleEncodeText' but specialised the @f@ to 'Data.Functor.Identity'.
simplePureEncodeText
  :: Encoder Identity a
  -> a
  -> LT.Text
simplePureEncodeText :: Encoder Identity a -> a -> Text
simplePureEncodeText Encoder Identity a
enc =
  Identity Text -> Text
forall a. Identity a -> a
runIdentity (Identity Text -> Text) -> (a -> Identity Text) -> a -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder Identity a -> a -> Identity Text
forall (f :: * -> *) a. Applicative f => Encoder f a -> a -> f Text
simpleEncodeText Encoder Identity a
enc

-- | As per 'simpleEncodeTextNoSpaces' but specialised the @f@ to 'Data.Functor.Identity'.
simplePureEncodeTextNoSpaces
  :: Encoder Identity a
  -> a
  -> LT.Text
simplePureEncodeTextNoSpaces :: Encoder Identity a -> a -> Text
simplePureEncodeTextNoSpaces Encoder Identity a
enc =
  Identity Text -> Text
forall a. Identity a -> a
runIdentity (Identity Text -> Text) -> (a -> Identity Text) -> a -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder Identity a -> a -> Identity Text
forall (f :: * -> *) a. Applicative f => Encoder f a -> a -> f Text
simpleEncodeTextNoSpaces Encoder Identity a
enc

-- | As per 'simpleEncodeByteString' but specialised the @f@ to 'Data.Functor.Identity'.
simplePureEncodeByteString
  :: Encoder Identity a
  -> a
  -> BL.ByteString
simplePureEncodeByteString :: Encoder Identity a -> a -> ByteString
simplePureEncodeByteString Encoder Identity a
enc =
  Identity ByteString -> ByteString
forall a. Identity a -> a
runIdentity (Identity ByteString -> ByteString)
-> (a -> Identity ByteString) -> a -> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder Identity a -> a -> Identity ByteString
forall (f :: * -> *) a.
Applicative f =>
Encoder f a -> a -> f ByteString
simpleEncodeByteString Encoder Identity a
enc

-- | As per 'simpleEncodeByteStringNoSpaces' but specialised the @f@ to 'Data.Functor.Identity'.
simplePureEncodeByteStringNoSpaces
  :: Encoder Identity a
  -> a
  -> BL.ByteString
simplePureEncodeByteStringNoSpaces :: Encoder Identity a -> a -> ByteString
simplePureEncodeByteStringNoSpaces Encoder Identity a
enc =
  Identity ByteString -> ByteString
forall a. Identity a -> a
runIdentity (Identity ByteString -> ByteString)
-> (a -> Identity ByteString) -> a -> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder Identity a -> a -> Identity ByteString
forall (f :: * -> *) a.
Applicative f =>
Encoder f a -> a -> f ByteString
simpleEncodeByteStringNoSpaces Encoder Identity a
enc

-- | Transform the given input using the 'Encoder' to its 'Json' data structure representation.
asJson :: Applicative f => Encoder f a -> a -> f Json
asJson :: Encoder f a -> a -> f Json
asJson = Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder
{-# INLINE asJson #-}

-- | As per 'asJson', but with the 'Encoder' specialised to 'Identity'
asJson' :: Encoder Identity a -> a -> Json
asJson' :: Encoder Identity a -> a -> Json
asJson' Encoder Identity a
e = Identity Json -> Json
forall a. Identity a -> a
runIdentity (Identity Json -> Json) -> (a -> Identity Json) -> a -> Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder Identity a -> a -> Identity Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder Identity a
e
{-# INLINE asJson' #-}

-- | 'Encoder'' for a Waargonaut 'Json' data structure
json :: Applicative f => Encoder f Json
json :: Encoder f Json
json = (Json -> f Json) -> Encoder f Json
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA Json -> f Json
forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE json #-}

-- Internal function for creating an 'Encoder' from an 'Control.Lens.AReview'.
encToJsonNoSpaces
  :: ( Monoid t
     , Applicative f
     )
  => AReview Json (b, t)
  -> (a -> b)
  -> Encoder f a
encToJsonNoSpaces :: AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (b, t)
c a -> b
f =
  (a -> f Json) -> Encoder f a
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA (Json -> f Json
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Json -> f Json) -> (a -> Json) -> a -> f Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AReview Json (b, t) -> (b, t) -> Json
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review AReview Json (b, t)
c ((b, t) -> Json) -> (a -> (b, t)) -> a -> Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (,t
forall a. Monoid a => a
mempty) (b -> (b, t)) -> (a -> b) -> a -> (b, t)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> b
f)

-- | Build an 'Encoder' using a 'Control.Lens.Prism''
prismE
  :: Prism' a b
  -> Encoder f a
  -> Encoder f b
prismE :: Prism' a b -> Encoder f a -> Encoder f b
prismE Prism' a b
p Encoder f a
e =
  AReview a b -> b -> a
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
L.review AReview a b
Prism' a b
p (b -> a) -> Encoder f a -> Encoder f b
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< Encoder f a
e
{-# INLINE prismE #-}

-- | Encode an 'Int'
int :: Applicative f => Encoder f Int
int :: Encoder f Int
int = AReview Json (JNumber, WS) -> (Int -> JNumber) -> Encoder f Int
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (JNumber, WS)
forall r ws a. AsJType r ws a => Prism' r (JNumber, ws)
_JNum (Tagged Int (Identity Int) -> Tagged JNumber (Identity JNumber)
Prism' JNumber Int
_JNumberInt (Tagged Int (Identity Int) -> Tagged JNumber (Identity JNumber))
-> Int -> JNumber
forall t b. AReview t b -> b -> t
#)

-- | Encode an 'Scientific'
scientific :: Applicative f => Encoder f Scientific
scientific :: Encoder f Scientific
scientific = AReview Json (JNumber, WS)
-> (Scientific -> JNumber) -> Encoder f Scientific
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (JNumber, WS)
forall r ws a. AsJType r ws a => Prism' r (JNumber, ws)
_JNum (Tagged Scientific (Identity Scientific)
-> Tagged JNumber (Identity JNumber)
Prism' JNumber Scientific
_JNumberScientific (Tagged Scientific (Identity Scientific)
 -> Tagged JNumber (Identity JNumber))
-> Scientific -> JNumber
forall t b. AReview t b -> b -> t
#)

-- | Encode a numeric value of the typeclass 'Integral'
integral :: (Applicative f, Integral n) => Encoder f n
integral :: Encoder f n
integral = AReview Json (JNumber, WS) -> (n -> JNumber) -> Encoder f n
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (JNumber, WS)
forall r ws a. AsJType r ws a => Prism' r (JNumber, ws)
_JNum ((Tagged Scientific (Identity Scientific)
 -> Tagged JNumber (Identity JNumber))
-> Scientific -> JNumber
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review Tagged Scientific (Identity Scientific)
-> Tagged JNumber (Identity JNumber)
Prism' JNumber Scientific
_JNumberScientific (Scientific -> JNumber) -> (n -> Scientific) -> n -> JNumber
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. n -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral)

-- | Encode a 'Bool'
bool :: Applicative f => Encoder f Bool
bool :: Encoder f Bool
bool = AReview Json (Bool, WS) -> (Bool -> Bool) -> Encoder f Bool
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (Bool, WS)
forall r ws a. AsJType r ws a => Prism' r (Bool, ws)
_JBool Bool -> Bool
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

-- | Encode a 'String'
string :: Applicative f => Encoder f String
string :: Encoder f String
string = AReview Json (JString, WS)
-> (String -> JString) -> Encoder f String
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (JString, WS)
forall r ws a. AsJType r ws a => Prism' r (JString, ws)
_JStr String -> JString
stringToJString

-- | Encode a 'Text'
text :: Applicative f => Encoder f Text
text :: Encoder f Text
text = AReview Json (JString, WS) -> (Text -> JString) -> Encoder f Text
forall t (f :: * -> *) b a.
(Monoid t, Applicative f) =>
AReview Json (b, t) -> (a -> b) -> Encoder f a
encToJsonNoSpaces AReview Json (JString, WS)
forall r ws a. AsJType r ws a => Prism' r (JString, ws)
_JStr (Tagged Text (Identity Text) -> Tagged JString (Identity JString)
forall (p :: * -> * -> *) (f :: * -> *).
(Profunctor p, Applicative f) =>
p Text (f Text) -> p JString (f JString)
_JStringText (Tagged Text (Identity Text) -> Tagged JString (Identity JString))
-> Text -> JString
forall t b. AReview t b -> b -> t
#)

-- | Encode an explicit 'null'.
null :: Applicative f => Encoder f ()
null :: Encoder f ()
null = (() -> f Json) -> Encoder f ()
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA ((() -> f Json) -> Encoder f ()) -> (() -> f Json) -> Encoder f ()
forall a b. (a -> b) -> a -> b
$ f Json -> () -> f Json
forall a b. a -> b -> a
const (Json -> f Json
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Json -> f Json) -> Json -> f Json
forall a b. (a -> b) -> a -> b
$ Tagged WS (Identity WS) -> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r ws
_JNull (Tagged WS (Identity WS) -> Tagged Json (Identity Json))
-> WS -> Json
forall t b. AReview t b -> b -> t
# WS
forall a. Monoid a => a
mempty)

-- | Encode a 'Maybe' value, using the provided 'Encoder''s to handle the
-- different choices.
maybe
  :: Functor f
  => Encoder f ()
  -> Encoder f a
  -> Encoder f (Maybe a)
maybe :: Encoder f () -> Encoder f a -> Encoder f (Maybe a)
maybe Encoder f ()
encN = (Maybe a -> f Json) -> Encoder f (Maybe a)
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA
  ((Maybe a -> f Json) -> Encoder f (Maybe a))
-> (Encoder f a -> Maybe a -> f Json)
-> Encoder f a
-> Encoder f (Maybe a)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. f Json -> (a -> f Json) -> Maybe a -> f Json
forall b a. b -> (a -> b) -> Maybe a -> b
Maybe.maybe (Encoder f () -> () -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder f ()
encN ())
  ((a -> f Json) -> Maybe a -> f Json)
-> (Encoder f a -> a -> f Json) -> Encoder f a -> Maybe a -> f Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder

-- | Encode a 'Maybe a' to either 'Encoder a' or 'null'
maybeOrNull
  :: Applicative f
  => Encoder f a
  -> Encoder f (Maybe a)
maybeOrNull :: Encoder f a -> Encoder f (Maybe a)
maybeOrNull =
  Encoder f () -> Encoder f a -> Encoder f (Maybe a)
forall (f :: * -> *) a.
Functor f =>
Encoder f () -> Encoder f a -> Encoder f (Maybe a)
maybe Encoder f ()
forall (f :: * -> *). Applicative f => Encoder f ()
null

-- | Encode an 'Either' value using the given 'Encoder's
either
  :: Functor f
  => Encoder f a
  -> Encoder f b
  -> Encoder f (Either a b)
either :: Encoder f a -> Encoder f b -> Encoder f (Either a b)
either Encoder f a
eA = (Either a b -> f Json) -> Encoder f (Either a b)
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA
  ((Either a b -> f Json) -> Encoder f (Either a b))
-> (Encoder f b -> Either a b -> f Json)
-> Encoder f b
-> Encoder f (Either a b)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> f Json) -> (b -> f Json) -> Either a b -> f Json
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
Either.either (Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder f a
eA)
  ((b -> f Json) -> Either a b -> f Json)
-> (Encoder f b -> b -> f Json)
-> Encoder f b
-> Either a b
-> f Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Encoder f b -> b -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder

-- | Encode some 'Traversable' of @a@ into a JSON array.
traversable
  :: ( Applicative f
     , Traversable t
     )
  => Encoder f a
  -> Encoder f (t a)
traversable :: Encoder f a -> Encoder f (t a)
traversable = (t Json -> Json) -> Encoder f a -> Encoder f (t a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
(t Json -> Json) -> Encoder f a -> Encoder f (t a)
encodeWithInner
  (\t Json
xs -> Tagged (JArray WS Json, WS) (Identity (JArray WS Json, WS))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JArray ws a, ws)
_JArr (Tagged (JArray WS Json, WS) (Identity (JArray WS Json, WS))
 -> Tagged Json (Identity Json))
-> (JArray WS Json, WS) -> Json
forall t b. AReview t b -> b -> t
# (Tagged (CommaSeparated WS Json) (Identity (CommaSeparated WS Json))
-> Tagged (JArray WS Json) (Identity (JArray WS Json))
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped (Tagged
   (CommaSeparated WS Json) (Identity (CommaSeparated WS Json))
 -> Tagged (JArray WS Json) (Identity (JArray WS Json)))
-> CommaSeparated WS Json -> JArray WS Json
forall t b. AReview t b -> b -> t
# (Json -> CommaSeparated WS Json -> CommaSeparated WS Json)
-> CommaSeparated WS Json -> t Json -> CommaSeparated WS Json
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Json -> CommaSeparated WS Json -> CommaSeparated WS Json
forall s a. Cons s s a a => a -> s -> s
cons CommaSeparated WS Json
forall a. Monoid a => a
mempty t Json
xs, WS
forall a. Monoid a => a
mempty))

-- | Encode a 'Map' in a JSON object.
mapToObj
  :: Applicative f
  => Encoder f a
  -> (k -> Text)
  -> Encoder f (Map k a)
mapToObj :: Encoder f a -> (k -> Text) -> Encoder f (Map k a)
mapToObj Encoder f a
encodeVal k -> Text
kToText =
  let
    mapToCS :: Map k Json -> MapLikeObj WS Json
mapToCS = (k -> Json -> MapLikeObj WS Json -> MapLikeObj WS Json)
-> MapLikeObj WS Json -> Map k Json -> MapLikeObj WS Json
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey (\k
k Json
v -> Index (MapLikeObj WS Json)
-> Lens'
     (MapLikeObj WS Json) (Maybe (IxValue (MapLikeObj WS Json)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at (k -> Text
kToText k
k) ((Maybe Json -> Identity (Maybe Json))
 -> MapLikeObj WS Json -> Identity (MapLikeObj WS Json))
-> Json -> MapLikeObj WS Json -> MapLikeObj WS Json
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Json
v) (Tagged () (Identity ())
-> Tagged (MapLikeObj WS Json) (Identity (MapLikeObj WS Json))
forall a. AsEmpty a => Prism' a ()
_Empty (Tagged () (Identity ())
 -> Tagged (MapLikeObj WS Json) (Identity (MapLikeObj WS Json)))
-> () -> MapLikeObj WS Json
forall t b. AReview t b -> b -> t
# ())
  in
    (Map k Json -> Json) -> Encoder f a -> Encoder f (Map k a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
(t Json -> Json) -> Encoder f a -> Encoder f (t a)
encodeWithInner (\Map k Json
xs -> Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JObject ws a, ws)
_JObj (Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
 -> Tagged Json (Identity Json))
-> (JObject WS Json, WS) -> Json
forall t b. AReview t b -> b -> t
# (MapLikeObj WS Json -> JObject WS Json
forall ws a. MapLikeObj ws a -> JObject ws a
fromMapLikeObj (MapLikeObj WS Json -> JObject WS Json)
-> MapLikeObj WS Json -> JObject WS Json
forall a b. (a -> b) -> a -> b
$ Map k Json -> MapLikeObj WS Json
mapToCS Map k Json
xs, WS
forall a. Monoid a => a
mempty)) Encoder f a
encodeVal

-- | Encode a 'NonEmpty' list
nonempty
  :: Applicative f
  => Encoder f a
  -> Encoder f (NonEmpty a)
nonempty :: Encoder f a -> Encoder f (NonEmpty a)
nonempty =
  Encoder f a -> Encoder f (NonEmpty a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable

-- | Encode a list
list
  :: Applicative f
  => Encoder f a
  -> Encoder f [a]
list :: Encoder f a -> Encoder f [a]
list =
  Encoder f a -> Encoder f [a]
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable

-- | As per 'json' but with the @f@ specialised to 'Data.Functor.Identity'.
json' :: Encoder' Json
json' :: Encoder' Json
json' = Encoder' Json
forall (f :: * -> *). Applicative f => Encoder f Json
json

-- | As per 'int' but with the @f@ specialised to 'Data.Functor.Identity'.
int' :: Encoder' Int
int' :: Encoder' Int
int' = Encoder' Int
forall (f :: * -> *). Applicative f => Encoder f Int
int

-- | As per 'integral' but with the @f@ specialised to 'Data.Functor.Identity'.
integral' :: Integral n => Encoder' n
integral' :: Encoder' n
integral' = Encoder' n
forall (f :: * -> *) n. (Applicative f, Integral n) => Encoder f n
integral

-- | As per 'scientific' but with the @f@ specialised to 'Data.Functor.Identity'.
scientific' :: Encoder' Scientific
scientific' :: Encoder' Scientific
scientific' = Encoder' Scientific
forall (f :: * -> *). Applicative f => Encoder f Scientific
scientific

-- | As per 'bool' but with the @f@ specialised to 'Data.Functor.Identity'.
bool' :: Encoder' Bool
bool' :: Encoder' Bool
bool' = Encoder' Bool
forall (f :: * -> *). Applicative f => Encoder f Bool
bool

-- | As per 'string' but with the @f@ specialised to 'Data.Functor.Identity'.
string' :: Encoder' String
string' :: Encoder' String
string' = Encoder' String
forall (f :: * -> *). Applicative f => Encoder f String
string

-- | As per 'text' but with the @f@ specialised to 'Data.Functor.Identity'.
text' :: Encoder' Text
text' :: Encoder' Text
text' = Encoder' Text
forall (f :: * -> *). Applicative f => Encoder f Text
text

-- | As per 'null' but with the @f@ specialised to 'Data.Functor.Identity'.
null' :: Encoder' ()
null' :: Encoder' ()
null' = Encoder' ()
forall (f :: * -> *). Applicative f => Encoder f ()
null

-- | As per 'maybe' but with the @f@ specialised to 'Data.Functor.Identity'.
maybe'
  :: Encoder' ()
  -> Encoder' a
  -> Encoder' (Maybe a)
maybe' :: Encoder' () -> Encoder' a -> Encoder' (Maybe a)
maybe' =
  Encoder' () -> Encoder' a -> Encoder' (Maybe a)
forall (f :: * -> *) a.
Functor f =>
Encoder f () -> Encoder f a -> Encoder f (Maybe a)
maybe

-- | As per 'maybeOrNull' but with the @f@ specialised to 'Data.Functor.Identity'.
maybeOrNull'
  :: Encoder' a
  -> Encoder' (Maybe a)
maybeOrNull' :: Encoder' a -> Encoder' (Maybe a)
maybeOrNull' =
  Encoder' a -> Encoder' (Maybe a)
forall (f :: * -> *) a.
Applicative f =>
Encoder f a -> Encoder f (Maybe a)
maybeOrNull

-- | As per 'either' but with the @f@ specialised to 'Data.Functor.Identity'.
either'
  :: Encoder' a
  -> Encoder' b
  -> Encoder' (Either a b)
either' :: Encoder' a -> Encoder' b -> Encoder' (Either a b)
either' =
  Encoder' a -> Encoder' b -> Encoder' (Either a b)
forall (f :: * -> *) a b.
Functor f =>
Encoder f a -> Encoder f b -> Encoder f (Either a b)
either

-- | As per 'nonempty' but with the @f@ specialised to 'Data.Functor.Identity'.
nonempty'
  :: Encoder' a
  -> Encoder' (NonEmpty a)
nonempty' :: Encoder' a -> Encoder' (NonEmpty a)
nonempty' =
  Encoder' a -> Encoder' (NonEmpty a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable

-- | As per 'list' but with the @f@ specialised to 'Data.Functor.Identity'.
list'
  :: Encoder' a
  -> Encoder' [a]
list' :: Encoder' a -> Encoder' [a]
list' =
  Encoder' a -> Encoder' [a]
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable

-- | Encode some @a@ that is contained with another @t@ structure.
encodeWithInner
  :: ( Applicative f
     , Traversable t
     )
  => (t Json -> Json)
  -> Encoder f a
  -> Encoder f (t a)
encodeWithInner :: (t Json -> Json) -> Encoder f a -> Encoder f (t a)
encodeWithInner t Json -> Json
f Encoder f a
g =
  (t a -> f Json) -> Encoder f (t a)
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
jsonEncoder ((t a -> f Json) -> Encoder f (t a))
-> (t a -> f Json) -> Encoder f (t a)
forall a b. (a -> b) -> a -> b
$ (t Json -> Json) -> f (t Json) -> f Json
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap t Json -> Json
f (f (t Json) -> f Json) -> (t a -> f (t Json)) -> t a -> f Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> f Json) -> t a -> f (t Json)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder f a
g)

-- | As per 'traversable' but with the @f@ specialised to 'Data.Functor.Identity'.
traversable'
  :: Traversable t
  => Encoder' a
  -> Encoder' (t a)
traversable' :: Encoder' a -> Encoder' (t a)
traversable' =
  Encoder' a -> Encoder' (t a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable

-- | Using the given function to convert the @k@ type keys to a 'Text' value,
-- encode a 'Map' as a JSON object.
mapToObj'
  :: Encoder' a
  -> (k -> Text)
  -> Encoder' (Map k a)
mapToObj' :: Encoder' a -> (k -> Text) -> Encoder' (Map k a)
mapToObj' =
  Encoder' a -> (k -> Text) -> Encoder' (Map k a)
forall (f :: * -> *) a k.
Applicative f =>
Encoder f a -> (k -> Text) -> Encoder f (Map k a)
mapToObj

-- | When encoding a 'MapLikeObj', this function lets you encode a value at a specific key
atKey
  :: ( At t
     , IxValue t ~ Json
     , Applicative f
     )
  => Index t
  -> Encoder f a
  -> a
  -> t
  -> f t
atKey :: Index t -> Encoder f a -> a -> t -> f t
atKey Index t
k Encoder f a
enc a
v t
t =
  (\Json
v' -> t
t t -> (t -> t) -> t
forall a b. a -> (a -> b) -> b
& Index t -> Lens' t (Maybe (IxValue t))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Index t
k ((Maybe Json -> Identity (Maybe Json)) -> t -> Identity t)
-> Json -> t -> t
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Json
v') (Json -> t) -> f Json -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Encoder f a -> a -> f Json
forall (f :: * -> *) i a.
Functor f =>
EncoderFns i f a -> a -> f Json
runEncoder Encoder f a
enc a
v

-- | Optionally encode an @a@ if it is a @Just a@. A @Nothing@ will result in the key being absent from the object.
atOptKey
  :: ( At t
     , IxValue t ~ Json
     , Applicative f
     )
  => Index t
  -> Encoder f a
  -> Maybe a
  -> t
  -> f t
atOptKey :: Index t -> Encoder f a -> Maybe a -> t -> f t
atOptKey Index t
k Encoder f a
enc =
  (t -> f t) -> (a -> t -> f t) -> Maybe a -> t -> f t
forall b a. b -> (a -> b) -> Maybe a -> b
Maybe.maybe t -> f t
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Index t -> Encoder f a -> a -> t -> f t
forall t (f :: * -> *) a.
(At t, IxValue t ~ Json, Applicative f) =>
Index t -> Encoder f a -> a -> t -> f t
atKey Index t
k Encoder f a
enc)

-- | Encode an @a@ at the given index on the JSON object.
atKey'
  :: ( At t
     , IxValue t ~ Json
     )
  => Index t
  -> Encoder' a
  -> a
  -> t
  -> t
atKey' :: Index t -> Encoder' a -> a -> t -> t
atKey' Index t
k Encoder' a
enc a
v =
  Index t -> Lens' t (Maybe (IxValue t))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Index t
k ((Maybe Json -> Identity (Maybe Json)) -> t -> Identity t)
-> Json -> t -> t
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Encoder' a -> a -> Json
forall a. Encoder Identity a -> a -> Json
asJson' Encoder' a
enc a
v
{-# INLINE atKey' #-}

-- | Optionally encode a @key : value@ pair on an object.
--
-- @
-- encoder = E.mapLikeObj \$ \\a ->
--   atKey' \"A\" E.text (_getterA a)
--   atOptKey' \"B\" E.int (_maybeB a)
--
-- simplePureEncodeByteString encoder (Foo "bob" (Just 33)) = "{\"A\":\"bob\",\"B\":33}"
--
-- simplePureEncodeByteString encoder (Foo "bob" Nothing) = "{\"A\":\"bob\"}"
--
-- @
--
atOptKey'
  :: ( At t
     , IxValue t ~ Json
     )
  => Index t
  -> Encoder' a
  -> Maybe a
  -> t
  -> t
atOptKey' :: Index t -> Encoder' a -> Maybe a -> t -> t
atOptKey' Index t
k Encoder' a
enc =
  (t -> t) -> (a -> t -> t) -> Maybe a -> t -> t
forall b a. b -> (a -> b) -> Maybe a -> b
Maybe.maybe t -> t
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id (Index t -> Encoder' a -> a -> t -> t
forall t a.
(At t, IxValue t ~ Json) =>
Index t -> Encoder' a -> a -> t -> t
atKey' Index t
k Encoder' a
enc)
{-# INLINE atOptKey' #-}

-- | Encode an 'Int' at the given 'Text' key.
intAt
  :: Text
  -> Int
  -> MapLikeObj WS Json
  -> MapLikeObj WS Json
intAt :: Text -> Int -> MapLikeObj WS Json -> MapLikeObj WS Json
intAt =
  (Text
 -> Encoder' Int -> Int -> MapLikeObj WS Json -> MapLikeObj WS Json)
-> Encoder' Int
-> Text
-> Int
-> MapLikeObj WS Json
-> MapLikeObj WS Json
forall a b c. (a -> b -> c) -> b -> a -> c
flip Text
-> Encoder' Int -> Int -> MapLikeObj WS Json -> MapLikeObj WS Json
forall t a.
(At t, IxValue t ~ Json) =>
Index t -> Encoder' a -> a -> t -> t
atKey' Encoder' Int
forall (f :: * -> *). Applicative f => Encoder f Int
int

-- | Encode a 'Text' value at the given 'Text' key.
textAt
  :: Text
  -> Text
  -> MapLikeObj WS Json
  -> MapLikeObj WS Json
textAt :: Text -> Text -> MapLikeObj WS Json -> MapLikeObj WS Json
textAt =
  (Text
 -> Encoder' Text
 -> Text
 -> MapLikeObj WS Json
 -> MapLikeObj WS Json)
-> Encoder' Text
-> Text
-> Text
-> MapLikeObj WS Json
-> MapLikeObj WS Json
forall a b c. (a -> b -> c) -> b -> a -> c
flip Text
-> Encoder' Text
-> Text
-> MapLikeObj WS Json
-> MapLikeObj WS Json
forall t a.
(At t, IxValue t ~ Json) =>
Index t -> Encoder' a -> a -> t -> t
atKey' Encoder' Text
forall (f :: * -> *). Applicative f => Encoder f Text
text

-- | Encode a 'Bool' at the given 'Text' key.
boolAt
  :: Text
  -> Bool
  -> MapLikeObj WS Json
  -> MapLikeObj WS Json
boolAt :: Text -> Bool -> MapLikeObj WS Json -> MapLikeObj WS Json
boolAt =
  (Text
 -> Encoder' Bool
 -> Bool
 -> MapLikeObj WS Json
 -> MapLikeObj WS Json)
-> Encoder' Bool
-> Text
-> Bool
-> MapLikeObj WS Json
-> MapLikeObj WS Json
forall a b c. (a -> b -> c) -> b -> a -> c
flip Text
-> Encoder' Bool
-> Bool
-> MapLikeObj WS Json
-> MapLikeObj WS Json
forall t a.
(At t, IxValue t ~ Json) =>
Index t -> Encoder' a -> a -> t -> t
atKey' Encoder' Bool
forall (f :: * -> *). Applicative f => Encoder f Bool
bool

-- | Encode a 'Foldable' of @a@ at the given index on a JSON object.
traversableAt
  :: ( At t
     , Traversable f
     , IxValue t ~ Json
     )
  => Encoder' a
  -> Index t
  -> f a
  -> t
  -> t
traversableAt :: Encoder' a -> Index t -> f a -> t -> t
traversableAt Encoder' a
enc =
  (Index t -> Encoder' (f a) -> f a -> t -> t)
-> Encoder' (f a) -> Index t -> f a -> t -> t
forall a b c. (a -> b -> c) -> b -> a -> c
flip Index t -> Encoder' (f a) -> f a -> t -> t
forall t a.
(At t, IxValue t ~ Json) =>
Index t -> Encoder' a -> a -> t -> t
atKey' (Encoder' a -> Encoder' (f a)
forall (f :: * -> *) (t :: * -> *) a.
(Applicative f, Traversable t) =>
Encoder f a -> Encoder f (t a)
traversable Encoder' a
enc)

-- | Encode a standard Haskell list at the given index on a JSON object.
listAt
  :: ( At t
     , IxValue t ~ Json
     )
  => Encoder' a
  -> Index t
  -> [a]
  -> t
  -> t
listAt :: Encoder' a -> Index t -> [a] -> t -> t
listAt =
  Encoder' a -> Index t -> [a] -> t -> t
forall t (f :: * -> *) a.
(At t, Traversable f, IxValue t ~ Json) =>
Encoder' a -> Index t -> f a -> t -> t
traversableAt

-- | Encode a 'NonEmpty' list at the given index on a JSON object.
nonemptyAt
  :: ( At t
     , IxValue t ~ Json
     )
  => Encoder' a
  -> Index t
  -> NonEmpty a
  -> t
  -> t
nonemptyAt :: Encoder' a -> Index t -> NonEmpty a -> t -> t
nonemptyAt =
  Encoder' a -> Index t -> NonEmpty a -> t -> t
forall t (f :: * -> *) a.
(At t, Traversable f, IxValue t ~ Json) =>
Encoder' a -> Index t -> f a -> t -> t
traversableAt

-- | Apply a function to update a 'MapLikeObj' and encode that as a JSON object.
--
-- For example, given the following data type:
--
-- @
-- data Image = Image
--   { _imageW        :: Int
--   , _imageH        :: Int
--   , _imageTitle    :: Text
--   , _imageAnimated :: Bool
--   , _imageIDs      :: [Int]
--   }
-- @
--
-- We can use this function to create an encoder, composing the individual
-- update functions to set the keys and values as desired.
--
-- @
-- encodeImage :: Applicative f => Encoder f Image
-- encodeImage = mapLikeObj $ \\img ->
--   intAt \"Width\" (_imageW img) .           -- ^ Set an 'Int' value at the \"Width\" key.
--   intAt \"Height\" (_imageH img) .
--   textAt \"Title\" (_imageTitle img) .
--   boolAt \"Animated\" (_imageAnimated img) .
--   listAt int \"IDs\" (_imageIDs img) -- ^ Set an @[Int]@ value at the \"IDs\" key.
-- @
--
mapLikeObj
  :: ( AsJType Json ws a
     , Monoid ws
     , Semigroup ws
     , Applicative f
     )
  => (i -> MapLikeObj ws a -> MapLikeObj ws a)
  -> Encoder f i
mapLikeObj :: (i -> MapLikeObj ws a -> MapLikeObj ws a) -> Encoder f i
mapLikeObj i -> MapLikeObj ws a -> MapLikeObj ws a
f = (i -> f Json) -> Encoder f i
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA ((i -> f Json) -> Encoder f i) -> (i -> f Json) -> Encoder f i
forall a b. (a -> b) -> a -> b
$ \i
a ->
  Json -> f Json
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Json -> f Json) -> Json -> f Json
forall a b. (a -> b) -> a -> b
$ Tagged (JObject ws a, ws) (Identity (JObject ws a, ws))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JObject ws a, ws)
_JObj (Tagged (JObject ws a, ws) (Identity (JObject ws a, ws))
 -> Tagged Json (Identity Json))
-> (JObject ws a, ws) -> Json
forall t b. AReview t b -> b -> t
# (MapLikeObj ws a -> JObject ws a
forall ws a. MapLikeObj ws a -> JObject ws a
fromMapLikeObj (MapLikeObj ws a -> JObject ws a)
-> MapLikeObj ws a -> JObject ws a
forall a b. (a -> b) -> a -> b
$ i -> MapLikeObj ws a -> MapLikeObj ws a
f i
a (Tagged () (Identity ())
-> Tagged (MapLikeObj ws a) (Identity (MapLikeObj ws a))
forall a. AsEmpty a => Prism' a ()
_Empty (Tagged () (Identity ())
 -> Tagged (MapLikeObj ws a) (Identity (MapLikeObj ws a)))
-> () -> MapLikeObj ws a
forall t b. AReview t b -> b -> t
# ()), ws
forall a. Monoid a => a
mempty)

-- | As per 'mapLikeObj' but specialised for 'Identity' as the 'Applicative'.
mapLikeObj'
  :: ( AsJType Json ws a
     , Semigroup ws
     , Monoid ws
     )
  => (i -> MapLikeObj ws a -> MapLikeObj ws a)
  -> Encoder' i
mapLikeObj' :: (i -> MapLikeObj ws a -> MapLikeObj ws a) -> Encoder' i
mapLikeObj' i -> MapLikeObj ws a -> MapLikeObj ws a
f = (i -> Json) -> Encoder' i
forall a. (a -> Json) -> Encoder' a
encodePureA ((i -> Json) -> Encoder' i) -> (i -> Json) -> Encoder' i
forall a b. (a -> b) -> a -> b
$ \i
a ->
  Tagged (JObject ws a, ws) (Identity (JObject ws a, ws))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JObject ws a, ws)
_JObj (Tagged (JObject ws a, ws) (Identity (JObject ws a, ws))
 -> Tagged Json (Identity Json))
-> (JObject ws a, ws) -> Json
forall t b. AReview t b -> b -> t
# (MapLikeObj ws a -> JObject ws a
forall ws a. MapLikeObj ws a -> JObject ws a
fromMapLikeObj (MapLikeObj ws a -> JObject ws a)
-> MapLikeObj ws a -> JObject ws a
forall a b. (a -> b) -> a -> b
$ i -> MapLikeObj ws a -> MapLikeObj ws a
f i
a (Tagged () (Identity ())
-> Tagged (MapLikeObj ws a) (Identity (MapLikeObj ws a))
forall a. AsEmpty a => Prism' a ()
_Empty (Tagged () (Identity ())
 -> Tagged (MapLikeObj ws a) (Identity (MapLikeObj ws a)))
-> () -> MapLikeObj ws a
forall t b. AReview t b -> b -> t
# ()), ws
forall a. Monoid a => a
mempty)

-- |
-- This function allows you to extend the fields on a JSON object created by a
-- separate encoder.
--
extendObject
  :: Functor f
  => ObjEncoder f a
  -> a
  -> (JObject WS Json -> JObject WS Json)
  -> f Json
extendObject :: ObjEncoder f a
-> a -> (JObject WS Json -> JObject WS Json) -> f Json
extendObject ObjEncoder f a
encA a
a JObject WS Json -> JObject WS Json
f =
  ObjEncoder f a -> JObject WS Json -> Json
forall i (f :: * -> *) a. EncoderFns i f a -> i -> Json
finaliseEncoding ObjEncoder f a
encA (JObject WS Json -> Json)
-> (JObject WS Json -> JObject WS Json) -> JObject WS Json -> Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JObject WS Json -> JObject WS Json
f (JObject WS Json -> Json) -> f (JObject WS Json) -> f Json
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ObjEncoder f a -> a -> f (JObject WS Json)
forall i (f :: * -> *) a. EncoderFns i f a -> a -> f i
initialEncoding ObjEncoder f a
encA a
a

-- |
-- This function lets you extend the fields on a JSON object but enforces the
-- uniqueness of the keys by working through the 'MapLikeObj' structure.
--
-- This will keep the first occurence of each unique key in the map. So be sure
-- to check your output.
--
extendMapLikeObject
  :: Functor f
  => ObjEncoder f a
  -> a
  -> (MapLikeObj WS Json -> MapLikeObj WS Json)
  -> f Json
extendMapLikeObject :: ObjEncoder f a
-> a -> (MapLikeObj WS Json -> MapLikeObj WS Json) -> f Json
extendMapLikeObject ObjEncoder f a
encA a
a MapLikeObj WS Json -> MapLikeObj WS Json
f =
  ObjEncoder f a -> JObject WS Json -> Json
forall i (f :: * -> *) a. EncoderFns i f a -> i -> Json
finaliseEncoding ObjEncoder f a
encA (JObject WS Json -> Json)
-> (JObject WS Json -> JObject WS Json) -> JObject WS Json -> Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JObject WS Json -> JObject WS Json
floopObj (JObject WS Json -> Json) -> f (JObject WS Json) -> f Json
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ObjEncoder f a -> a -> f (JObject WS Json)
forall i (f :: * -> *) a. EncoderFns i f a -> a -> f i
initialEncoding ObjEncoder f a
encA a
a
  where
    floopObj :: JObject WS Json -> JObject WS Json
floopObj = MapLikeObj WS Json -> JObject WS Json
forall ws a. MapLikeObj ws a -> JObject ws a
fromMapLikeObj (MapLikeObj WS Json -> JObject WS Json)
-> (JObject WS Json -> MapLikeObj WS Json)
-> JObject WS Json
-> JObject WS Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. MapLikeObj WS Json -> MapLikeObj WS Json
f (MapLikeObj WS Json -> MapLikeObj WS Json)
-> (JObject WS Json -> MapLikeObj WS Json)
-> JObject WS Json
-> MapLikeObj WS Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (MapLikeObj WS Json, [JAssoc WS Json]) -> MapLikeObj WS Json
forall a b. (a, b) -> a
fst ((MapLikeObj WS Json, [JAssoc WS Json]) -> MapLikeObj WS Json)
-> (JObject WS Json -> (MapLikeObj WS Json, [JAssoc WS Json]))
-> JObject WS Json
-> MapLikeObj WS Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JObject WS Json -> (MapLikeObj WS Json, [JAssoc WS Json])
forall ws a.
(Semigroup ws, Monoid ws) =>
JObject ws a -> (MapLikeObj ws a, [JAssoc ws a])
toMapLikeObj

-- |
-- Given encoders for things that are represented in JSON as @objects@, and a
-- way to get to the @b@ and @c@ from the @a@. This function lets you create an
-- encoder for @a@. The two objects are combined to make one single JSON object.
--
-- Given
--
-- @
-- encodeFoo :: ObjEncoder f Foo
-- encodeBar :: ObjEncoder f Bar
-- -- and some wrapping type:
-- data A = { _foo :: Foo, _bar :: Bar }
-- @
--
-- We can use this function to utilise our already defined 'ObjEncoder'
-- structures to give us an encoder for @A@:
--
-- @
-- combineObjects (\aRecord -> (_foo aRecord, _bar aRecord)) encodeFoo encodeBar :: ObjEncoder f Bar
-- @
--
combineObjects
  :: Applicative f
  => (a -> (b, c))
  -> ObjEncoder f b
  -> ObjEncoder f c
  -> ObjEncoder f a
combineObjects :: (a -> (b, c)) -> ObjEncoder f b -> ObjEncoder f c -> ObjEncoder f a
combineObjects =
  (a -> (b, c)) -> ObjEncoder f b -> ObjEncoder f c -> ObjEncoder f a
forall (f :: * -> *) a b c.
Divisible f =>
(a -> (b, c)) -> f b -> f c -> f a
divide

-- | When encoding a JSON object that may contain duplicate keys, this function
-- works the same as the 'atKey' function for 'MapLikeObj'.
onObj
  :: Applicative f
  => Text
  -> b
  -> Encoder f b
  -> JObject WS Json
  -> f (JObject WS Json)
onObj :: Text -> b -> Encoder f b -> JObject WS Json -> f (JObject WS Json)
onObj Text
k b
b Encoder f b
encB JObject WS Json
o = (\JAssoc WS Json
j -> JObject WS Json
o JObject WS Json
-> (JObject WS Json -> JObject WS Json) -> JObject WS Json
forall a b. a -> (a -> b) -> b
& (CommaSeparated WS (JAssoc WS Json)
 -> Identity (CommaSeparated WS (JAssoc WS Json)))
-> JObject WS Json -> Identity (JObject WS Json)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped ((CommaSeparated WS (JAssoc WS Json)
  -> Identity (CommaSeparated WS (JAssoc WS Json)))
 -> JObject WS Json -> Identity (JObject WS Json))
-> (CommaSeparated WS (JAssoc WS Json)
    -> CommaSeparated WS (JAssoc WS Json))
-> JObject WS Json
-> JObject WS Json
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
L.%~ JAssoc WS Json
-> CommaSeparated WS (JAssoc WS Json)
-> CommaSeparated WS (JAssoc WS Json)
forall s a. Cons s s a a => a -> s -> s
L.cons JAssoc WS Json
j)
  (JAssoc WS Json -> JObject WS Json)
-> (Json -> JAssoc WS Json) -> Json -> JObject WS Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JString -> WS -> WS -> Json -> JAssoc WS Json
forall ws a. JString -> ws -> ws -> a -> JAssoc ws a
JAssoc (Tagged Text (Identity Text) -> Tagged JString (Identity JString)
forall (p :: * -> * -> *) (f :: * -> *).
(Profunctor p, Applicative f) =>
p Text (f Text) -> p JString (f JString)
_JStringText (Tagged Text (Identity Text) -> Tagged JString (Identity JString))
-> Text -> JString
forall t b. AReview t b -> b -> t
# Text
k) WS
forall a. Monoid a => a
mempty WS
forall a. Monoid a => a
mempty (Json -> JObject WS Json) -> f Json -> f (JObject WS Json)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Encoder f b -> b -> f Json
forall (f :: * -> *) a. Applicative f => Encoder f a -> a -> f Json
asJson Encoder f b
encB b
b

-- | As per 'onObj' but the @f@ is specialised to 'Identity'.
onObj'
  :: Text
  -> b
  -> Encoder' b
  -> JObject WS Json
  -> JObject WS Json
onObj' :: Text -> b -> Encoder' b -> JObject WS Json -> JObject WS Json
onObj' Text
k b
b Encoder' b
encB JObject WS Json
o = (\JAssoc WS Json
j -> JObject WS Json
o JObject WS Json
-> (JObject WS Json -> JObject WS Json) -> JObject WS Json
forall a b. a -> (a -> b) -> b
& (CommaSeparated WS (JAssoc WS Json)
 -> Identity (CommaSeparated WS (JAssoc WS Json)))
-> JObject WS Json -> Identity (JObject WS Json)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped ((CommaSeparated WS (JAssoc WS Json)
  -> Identity (CommaSeparated WS (JAssoc WS Json)))
 -> JObject WS Json -> Identity (JObject WS Json))
-> (CommaSeparated WS (JAssoc WS Json)
    -> CommaSeparated WS (JAssoc WS Json))
-> JObject WS Json
-> JObject WS Json
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
L.%~ JAssoc WS Json
-> CommaSeparated WS (JAssoc WS Json)
-> CommaSeparated WS (JAssoc WS Json)
forall s a. Cons s s a a => a -> s -> s
L.cons JAssoc WS Json
j)
  (JAssoc WS Json -> JObject WS Json)
-> (Json -> JAssoc WS Json) -> Json -> JObject WS Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JString -> WS -> WS -> Json -> JAssoc WS Json
forall ws a. JString -> ws -> ws -> a -> JAssoc ws a
JAssoc (Tagged Text (Identity Text) -> Tagged JString (Identity JString)
forall (p :: * -> * -> *) (f :: * -> *).
(Profunctor p, Applicative f) =>
p Text (f Text) -> p JString (f JString)
_JStringText (Tagged Text (Identity Text) -> Tagged JString (Identity JString))
-> Text -> JString
forall t b. AReview t b -> b -> t
# Text
k) WS
forall a. Monoid a => a
mempty WS
forall a. Monoid a => a
mempty (Json -> JObject WS Json) -> Json -> JObject WS Json
forall a b. (a -> b) -> a -> b
$ Encoder' b -> b -> Json
forall a. Encoder Identity a -> a -> Json
asJson' Encoder' b
encB b
b

-- | Encode key value pairs as a JSON object, allowing duplicate keys.
keyValuesAsObj
  :: ( Foldable g
     , Monad f
     )
  => g (a -> JObject WS Json -> f (JObject WS Json))
  -> Encoder f a
keyValuesAsObj :: g (a -> JObject WS Json -> f (JObject WS Json)) -> Encoder f a
keyValuesAsObj g (a -> JObject WS Json -> f (JObject WS Json))
xs = (a -> f Json) -> Encoder f a
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA ((a -> f Json) -> Encoder f a) -> (a -> f Json) -> Encoder f a
forall a b. (a -> b) -> a -> b
$ \a
a ->
  (\JObject WS Json
v -> Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JObject ws a, ws)
_JObj (Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
 -> Tagged Json (Identity Json))
-> (JObject WS Json, WS) -> Json
forall t b. AReview t b -> b -> t
# (JObject WS Json
v,WS
forall a. Monoid a => a
mempty)) (JObject WS Json -> Json) -> f (JObject WS Json) -> f Json
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((a -> JObject WS Json -> f (JObject WS Json))
 -> JObject WS Json -> f (JObject WS Json))
-> JObject WS Json
-> g (a -> JObject WS Json -> f (JObject WS Json))
-> f (JObject WS Json)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> b -> m b) -> b -> t a -> m b
foldrM (\a -> JObject WS Json -> f (JObject WS Json)
f -> a -> JObject WS Json -> f (JObject WS Json)
f a
a) (Tagged () (Identity ())
-> Tagged (JObject WS Json) (Identity (JObject WS Json))
forall a. AsEmpty a => Prism' a ()
_Empty (Tagged () (Identity ())
 -> Tagged (JObject WS Json) (Identity (JObject WS Json)))
-> () -> JObject WS Json
forall t b. AReview t b -> b -> t
# ()) g (a -> JObject WS Json -> f (JObject WS Json))
xs

-- | Encode some 'Data.Foldable.Foldable' of @(Text, a)@ as a JSON object. This permits duplicate
-- keys.
keyValueTupleFoldable
  :: ( Monad f
     , Foldable g
     )
  => Encoder f a
  -> Encoder f (g (Text, a))
keyValueTupleFoldable :: Encoder f a -> Encoder f (g (Text, a))
keyValueTupleFoldable Encoder f a
eA = (g (Text, a) -> f Json) -> Encoder f (g (Text, a))
forall a (f :: * -> *). (a -> f Json) -> EncoderFns Json f a
encodeA ((g (Text, a) -> f Json) -> Encoder f (g (Text, a)))
-> (g (Text, a) -> f Json) -> Encoder f (g (Text, a))
forall a b. (a -> b) -> a -> b
$
  (JObject WS Json -> Json) -> f (JObject WS Json) -> f Json
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\JObject WS Json
v -> Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
-> Tagged Json (Identity Json)
forall r ws a. AsJType r ws a => Prism' r (JObject ws a, ws)
_JObj (Tagged (JObject WS Json, WS) (Identity (JObject WS Json, WS))
 -> Tagged Json (Identity Json))
-> (JObject WS Json, WS) -> Json
forall t b. AReview t b -> b -> t
# (JObject WS Json
v,WS
forall a. Monoid a => a
mempty)) (f (JObject WS Json) -> f Json)
-> (g (Text, a) -> f (JObject WS Json)) -> g (Text, a) -> f Json
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((Text, a) -> JObject WS Json -> f (JObject WS Json))
-> JObject WS Json -> g (Text, a) -> f (JObject WS Json)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> b -> m b) -> b -> t a -> m b
foldrM (\(Text
k,a
v) JObject WS Json
o -> Text -> a -> Encoder f a -> JObject WS Json -> f (JObject WS Json)
forall (f :: * -> *) b.
Applicative f =>
Text -> b -> Encoder f b -> JObject WS Json -> f (JObject WS Json)
onObj Text
k a
v Encoder f a
eA JObject WS Json
o) (Tagged () (Identity ())
-> Tagged (JObject WS Json) (Identity (JObject WS Json))
forall a. AsEmpty a => Prism' a ()
_Empty (Tagged () (Identity ())
 -> Tagged (JObject WS Json) (Identity (JObject WS Json)))
-> () -> JObject WS Json
forall t b. AReview t b -> b -> t
# ())

-- | As per 'keyValuesAsObj' but with the @f@ specialised to 'Identity'.
keyValuesAsObj'
  :: ( Foldable g
     , Functor g
     )
  => g (a -> JObject WS Json -> JObject WS Json)
  -> Encoder' a
keyValuesAsObj' :: g (a -> JObject WS Json -> JObject WS Json) -> Encoder' a
keyValuesAsObj' =
  g (a -> JObject WS Json -> Identity (JObject WS Json))
-> Encoder' a
forall (g :: * -> *) (f :: * -> *) a.
(Foldable g, Monad f) =>
g (a -> JObject WS Json -> f (JObject WS Json)) -> Encoder f a
keyValuesAsObj (g (a -> JObject WS Json -> Identity (JObject WS Json))
 -> Encoder' a)
-> (g (a -> JObject WS Json -> JObject WS Json)
    -> g (a -> JObject WS Json -> Identity (JObject WS Json)))
-> g (a -> JObject WS Json -> JObject WS Json)
-> Encoder' a
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((a -> JObject WS Json -> JObject WS Json)
 -> a -> JObject WS Json -> Identity (JObject WS Json))
-> g (a -> JObject WS Json -> JObject WS Json)
-> g (a -> JObject WS Json -> Identity (JObject WS Json))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\a -> JObject WS Json -> JObject WS Json
f a
a -> JObject WS Json -> Identity (JObject WS Json)
forall a. a -> Identity a
Identity (JObject WS Json -> Identity (JObject WS Json))
-> (JObject WS Json -> JObject WS Json)
-> JObject WS Json
-> Identity (JObject WS Json)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> JObject WS Json -> JObject WS Json
f a
a)

-- | Using a given 'Encoder', encode a key value pair on the JSON object, using
-- the accessor function to retrieve the value.
encAt
  :: Applicative f
  => Encoder f b
  -> Text
  -> (a -> b)
  -> a
  -> JObject WS Json
  -> f (JObject WS Json)
encAt :: Encoder f b
-> Text -> (a -> b) -> a -> JObject WS Json -> f (JObject WS Json)
encAt Encoder f b
e Text
k a -> b
f a
a =
  Text -> b -> Encoder f b -> JObject WS Json -> f (JObject WS Json)
forall (f :: * -> *) b.
Applicative f =>
Text -> b -> Encoder f b -> JObject WS Json -> f (JObject WS Json)
onObj Text
k (a -> b
f a
a) Encoder f b
e