Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Representing optional elements #2

alanz opened this Issue Aug 14, 2011 · 2 comments


None yet
2 participants

alanz commented Aug 14, 2011

I am trying to capture the Json for the Telehash protocol (http://telehash.org/proto.html).

I am stuck on representing an optional field in the message.

So in the code snippet below,

data TeleHashEntry = TeleHashEntry 
                     { teleRing :: Int
                     , teleSee  :: Maybe [T.Text]
                     , teleBr   :: Int
                     , teleTo   :: T.Text
                     -- , teleLine :: Maybe T.Text
                     -- , teleHop  :: Maybe T.Text
                     } deriving (Eq, Show)

telexJson = $(deriveIsos ''TeleHashEntry)

instance Json TeleHashEntry where
  grammar = telexJson . object
    ( prop "_ring"
    . prop ".see"
    . prop "_br"
    . prop "_to"
    -- . prop "_line"
    -- . prop "_hop"

How do I capture that _line and _hop are optional?

The equivalent representation in Aeson is

instance FromJSON TeleHashEntry
    parseJSON (Object v) = TeleHashEntry <$> 
                           v .:  "_ring" <*>
                           v .:? ".see"  <*>
                           v .:  "_br"   <*>
                           v .:  "_to"   <*>
                           v .:? "_line" <*>
                           v .:? "_hop"
    parseJSON _          = mzero

where the optional items are captured by .:?


PS, the balance of the code is at https://github.com/alanz/htelehash

@MedeaMelana MedeaMelana was assigned Aug 16, 2011


MedeaMelana commented Aug 16, 2011

Hi Alan,

You can do this using the choice operator <>:

instance Json TeleHashEntry where
  grammar = telexJson . object
    ( prop "_ring"
    . prop ".see"
    . prop "_br"
    . prop "_to"
    . optionalProp "_line"
    . optionalProp "_hop"

optionalProp :: Json a => String -> Iso (Object :- t) (Object :- Maybe a :- t)
optionalProp name = duck just . prop name <> duck nothing

You need the ducks there because you're in an object context. Function optionalProp should really be in the library itself (along with any other convenience functions aeson offers). I'll include it in a future version. Thanks. :-)

If you have any further questions, feel free to reopen this ticket.


alanz commented Aug 16, 2011

Works perfectly, thanks for the quick response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment