{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Data.Record.Generic.JSON (
gtoJSON
, gparseJSON
) where
import Data.Aeson
import Data.Aeson.Types
import Data.Proxy
import Data.String
import Data.Record.Generic
import qualified Data.Record.Generic.Rep as Rep
gtoJSON :: forall a. (Generic a, Constraints a ToJSON) => a -> Value
gtoJSON :: forall a. (Generic a, Constraints a ToJSON) => a -> Value
gtoJSON =
[Pair] -> Value
object
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Rep (K a) b -> [a]
Rep.collapse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a (f :: * -> *) (g :: * -> *) (h :: * -> *).
Generic a =>
(forall x. f x -> g x -> h x) -> Rep f a -> Rep g a -> Rep h a
Rep.zipWith (forall {k1} {k2} {k3} a b c (d :: k1) (e :: k2) (f :: k3).
(a -> b -> c) -> K a d -> K b e -> K c f
mapKKK forall a b. (a -> b) -> a -> b
$ \String
n Value
x -> (forall a. IsString a => String -> a
fromString String
n, Value
x)) (forall a. Metadata a -> Rep (K String) a
recordFieldNames Metadata a
md)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a (c :: * -> Constraint) (f :: * -> *) (g :: * -> *).
(Generic a, Constraints a c) =>
Proxy c -> (forall x. c x => f x -> g x) -> Rep f a -> Rep g a
Rep.cmap (forall {k} (t :: k). Proxy t
Proxy @ToJSON) (forall k a (b :: k). a -> K a b
K forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. I a -> a
unI)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Generic a => a -> Rep I a
from
where
md :: Metadata a
md = forall a (proxy :: * -> *). Generic a => proxy a -> Metadata a
metadata (forall {k} (t :: k). Proxy t
Proxy @a)
gparseJSON :: forall a. (Generic a, Constraints a FromJSON) => Value -> Parser a
gparseJSON :: forall a. (Generic a, Constraints a FromJSON) => Value -> Parser a
gparseJSON =
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject (forall a. Metadata a -> String
recordName Metadata a
md) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Generic a => Rep I a -> a
to forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) (f :: * -> *) a.
Applicative m =>
Rep (m :.: f) a -> m (Rep f a)
Rep.sequenceA forall b c a. (b -> c) -> (a -> b) -> a -> c
. Object -> Rep (Parser :.: I) a
aux)
where
md :: Metadata a
md = forall a (proxy :: * -> *). Generic a => proxy a -> Metadata a
metadata (forall {k} (t :: k). Proxy t
Proxy @a)
aux :: Object -> Rep (Parser :.: I) a
aux :: Object -> Rep (Parser :.: I) a
aux Object
obj =
forall a (c :: * -> Constraint) (f :: * -> *) (g :: * -> *).
(Generic a, Constraints a c) =>
Proxy c -> (forall x. c x => f x -> g x) -> Rep f a -> Rep g a
Rep.cmap
(forall {k} (t :: k). Proxy t
Proxy @FromJSON)
(\(K String
fld) -> forall l k (f :: l -> *) (g :: k -> l) (p :: k).
f (g p) -> (:.:) f g p
Comp (forall a. a -> I a
I forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall x. FromJSON x => String -> Parser x
getField String
fld))
(forall a. Metadata a -> Rep (K String) a
recordFieldNames Metadata a
md)
where
getField :: FromJSON x => String -> Parser x
getField :: forall x. FromJSON x => String -> Parser x
getField String
fld = Object
obj forall a. FromJSON a => Object -> Key -> Parser a
.: forall a. IsString a => String -> a
fromString String
fld