@@ -90,6 +90,7 @@ module Obelisk.Route
9090 , Decoder(..)
9191 , dmapEncoder
9292 , fieldMapEncoder
93+ , jsonEncoder
9394 ) where
9495
9596import Prelude hiding ((.), id)
@@ -102,6 +103,7 @@ import Control.Category.Associative
102103import Control.Category.Monoidal
103104import Control.Lens (Identity (..), Prism', makePrisms, itraverse, imap, prism, (^.), re, matching, (^?), _Just, _Nothing, Iso', from, view, Wrapped (..))
104105import Control.Monad.Except
106+import qualified Data.ByteString.Lazy as BSL
105107import Data.Dependent.Sum (DSum (..))
106108import Data.Dependent.Map (DMap)
107109import qualified Data.Dependent.Map as DMap
@@ -130,6 +132,8 @@ import qualified Numeric.Lens
130132import Obelisk.Route.TH
131133import Text.Read (readMaybe)
132134import Data.Tabulation
135+import qualified Data.Aeson as Aeson
136+import Data.Aeson (FromJSON, ToJSON)
133137
134138-- Design goals:
135139-- No start-up time on the frontend (not yet met)
@@ -349,7 +353,7 @@ maybeEncoder f g = shadowEncoder f g . maybeToEitherEncoder
349353justEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse a (Maybe a)
350354justEncoder = prismEncoder _Just
351355
352−-- |
356+-- | Encode () to 'Nothing'.
353357nothingEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse () (Maybe a)
354358nothingEncoder = prismEncoder _Nothing
355359
@@ -933,4 +937,20 @@ fieldMapEncoder = unsafeEncoder $ do
933937 Just (Identity v) -> return v
934938 }
935939
940+-- | Use ToJSON/FromJSON to encode to Text. The correctness of this encoder is dependent on the encoding being injective and round-tripping correctly.
941+jsonEncoder :: forall check parse r.
942+ ( ToJSON r
943+ , FromJSON r
944+ , Applicative check
945+ , MonadError Text parse
946+ )
947+ => Encoder check parse r Text
948+jsonEncoder = unsafeEncoder $ do
949+ pure $ EncoderImpl
950+ { _encoderImpl_encode = \r -> decodeUtf8 . BSL.toStrict $ Aeson.encode r
951+ , _encoderImpl_decode = \t -> case Aeson.eitherDecodeStrict $ encodeUtf8 t of
952+ Left err -> throwError ("jsonEncoder: " <> T.pack err)
953+ Right x -> return x
954+ }
955+
936956--TODO: decodeURIComponent as appropriate