Created
February 9, 2020 12:47
-
-
Save pwm/6c89322876e8e43927736ddd9c5ce101 to your computer and use it in GitHub Desktop.
a Jijo Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module JijoExample where | |
import Control.Category ((>>>)) | |
import Data.Aeson | |
import Data.Aeson.Types | |
import qualified Data.ByteString.Lazy.Char8 as BSL | |
import Data.Scientific (Scientific) | |
import Data.Text (Text) | |
import qualified Data.Text as Text | |
import qualified Data.Text.Lazy.Encoding as Text | |
import qualified Data.Text.Lazy.IO as Text | |
import GHC.Records (getField) | |
import Jijo.Definition | |
import Prelude | |
-- | |
newtype PosNumber = UnsafeMkPosNumber Scientific | |
deriving stock (Show, Eq, Ord) | |
getPosNumber :: PosNumber -> Scientific | |
getPosNumber (UnsafeMkPosNumber x) = x | |
mkPosNumber :: Scientific -> Either Text PosNumber | |
mkPosNumber x | |
| x > 0 = Right $ UnsafeMkPosNumber x | |
| otherwise = Left "NonPositiveNumber " | |
-- composing the (library provided) jNumber with our own validator | |
jPosNumber :: JDefinition Text Value PosNumber | |
jPosNumber = jNumber >>> jDefinition jValidate jEncode | |
where | |
jValidate t = case mkPosNumber t of | |
Left e -> jValidationFail e | |
Right v -> pure v | |
jEncode = getPosNumber | |
-- | |
data Person | |
= MkPerson | |
{ name :: Text, | |
age :: PosNumber, | |
height :: Maybe PosNumber | |
} | |
deriving stock (Show, Eq, Ord) | |
-- using applicative to build up a record validating its fields | |
jPerson :: JDefinition Text Value Person | |
jPerson = | |
defineJObject $ | |
MkPerson | |
<$> inJField "name" (getField @"name") jString | |
<*> inJField "age" (getField @"age") jPosNumber | |
<*> inOptJField "height" (getField @"height") jPosNumber | |
instance FromJSON Person where | |
parseJSON = (parseJSON_viaDefinition . mapJError Text.unpack) jPerson | |
instance ToJSON Person where | |
toJSON = toJSON_viaDefinition jPerson | |
-- | |
run :: IO () | |
run = do | |
j <- Text.encodeUtf8 <$> Text.getLine | |
case eitherDecode j >>= parseEither (parseJSON @Person) of | |
Left e -> putStrLn e | |
Right v -> print v >> BSL.putStrLn (encode v) | |
run | |
-- | |
{- | |
λ> run | |
{} | |
Error in $: $: missing field name | |
$: missing field age | |
{"name": null, "age": true} | |
Error in $: $.age: type not one of {number} | |
$.name: type not one of {string} | |
{"name": "foo", "age": -1} | |
Error in $: $.age: NonPositiveNumber | |
{"name": "foo", "age": 1} | |
MkPerson {name = "foo", age = UnsafeMkPosNumber 1.0, height = Nothing} | |
{"age":1,"name":"foo"} | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment