-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Help: What is the best way to encode optional fields? #59
Comments
You can use either You can pattern match on the constructors like you have in the data FancyProperty = FancyProperty {
total :: Int
average :: Int
required :: Bool
}
data BaseProperty = BaseProperty {
name :: Text,
description :: Text,
fancyProperties :: Maybe FancyProperty
} I tend to avoid records in sum types as it can become troublesome. |
I've ended up with this using the original record sum type: encodeProperty :: Applicative f => WE.Encoder f J.Property
encodeProperty = WE.mapLikeObj $ \jss ->
encodeProperty' jss .
WE.textAt "name" (name jss) .
WE.textAt "description" (J.description jss)
encodeProperty' :: Property -> WT.MapLikeObj WT.WS WT.Json -> WT.MapLikeObj WT.WS WT.Json
encodeProperty' jss@(SomeProperty {}) =
WE.textAt "type" "some"
encodeProperty' jss@(FancyProperty {}) =
WE.textAt "type" "fancy" .
maybe id (WE.boolAt "required") (required jss) |
You've plenty of options for how you choose to encode this, which is kind of the point of the library. :) Some alternatives: encodePropertyA :: Applicative f => E.Encoder f Property
encodePropertyA = E.mapLikeObj $ \case
SomeProperty nm desc ->
baseObj "some" nm desc
FancyProperty nm desc tot avg reqd ->
baseObj "fancy" nm desc
. E.atKey' "total" (E.maybeOrNull E.int) tot
. E.atKey' "average" (E.maybeOrNull E.int) avg
. E.atKey' "required" (E.maybeOrNull E.bool)reqd
where
baseObj t n d =
E.textAt "type" t
. E.textAt "name" n
. E.textAt "desc" d
encodePropertyB :: Monad f => E.Encoder f Property
encodePropertyB = E.encodeA $ \p -> E.extendMapLikeObject baseObj p $
case p of
SomeProperty _ _ -> E.atKey' "type" E.text "some"
FancyProperty _ _ tot avg reqd ->
E.atKey' "type" E.text "fancy"
. E.atKey' "total" (E.maybeOrNull E.int) tot
. E.atKey' "average" (E.maybeOrNull E.int) avg
. E.atKey' "required" (E.maybeOrNull E.bool)reqd
where
baseObj = E.objEncoder $ \p ->
E.onObj "name" (name p) E.text mempty >>=
E.onObj "description" (description p) E.text |
Thank you for including the example code. In my case I wanted to have the key entirely absent from the object if the value was Nothing rather than provide a default or null. I am writing a little utility to produce JSON Schema files for the input parameters of a set of MS SQL stored procedures. |
Waargonaut should be able to support that as well, although giving it a quick poke it is not as straight-forward as I remember. I might have to play with that and see what falls out, because having the option of either optional values, or optional key:value pairs is definitely a thing that needs to exist. Also if you work it out and want to point out the bits that didn't work or could be generalised then I'm all ears. 👍 |
Given a record like this:
I then want to write a property encoder that looks something like this:
The text was updated successfully, but these errors were encountered: