module Web.Hyperbole.Data.JSON (JSON (..), ToJSON, FromJSON) where

import Data.Aeson as A
import Data.String.Conversions (cs)
import Web.Hyperbole.Data.Encoded
import Web.Hyperbole.Data.Param


-- JSON Encoded Data ------------------------------------

-- | This type always encodes data via JSON
newtype JSON a = JSON a


instance (ToJSON a) => ToEncoded (JSON a) where
  toEncoded :: JSON a -> Encoded
toEncoded (JSON a
a) = ConName -> [ParamValue] -> Encoded
Encoded ConName
"" [a -> ParamValue
forall a. ToJSON a => a -> ParamValue
jsonParam a
a]
instance (FromJSON a) => FromEncoded (JSON a) where
  parseEncoded :: Encoded -> Either String (JSON a)
parseEncoded (Encoded ConName
_ [ParamValue Text
t]) = do
    a -> JSON a
forall a. a -> JSON a
JSON (a -> JSON a) -> Either String a -> Either String (JSON a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
A.eitherDecode (Text -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs Text
t)
  parseEncoded (Encoded ConName
_ [ParamValue]
prms) = do
    String -> Either String (JSON a)
forall a b. a -> Either a b
Left (String -> Either String (JSON a))
-> String -> Either String (JSON a)
forall a b. (a -> b) -> a -> b
$ String
"Could not parse JSON Encoded, expected one param: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [ParamValue] -> String
forall a. Show a => a -> String
show [ParamValue]
prms