aeson
aeson copied to clipboard
Consider general `toJSON` `toEncoding` implementation
I get fairly tired of implementing both toJSON and toEncoding for ToJSON, but it seems to me there's a solution, by extending the KeyValue concept a bit:
-- So we can use Monoid KeyValue instances
instance KeyValue [Pair] where
k .= v = [k .= v]
class (KeyValue p, Monoid p) => JSONRep p r | r -> p, p -> r where
repJSON :: ToJSON a => a -> r
repPair :: Text -> r -> p
repObject :: p -> r
repList :: [r] -> r
instance JSONRep [Pair] Value where
repJSON = toJSON
repPair = (.=)
repObject = object
repList = toJSON
instance JSONRep Series Encoding where
repJSON = toEncoding
repPair = pair
repObject = pairs
repList = list id
(The names and specifics are just for example -- I'm sure there are better options and variations of repList etc.)
This would allow a single implementation for many things:
myThingRep :: JSONRep p r => MyThing -> r
myThingRep t = repObject
$ "thing" J..= thing t
<> "values" `repPair` repList (map valueRep $ values t)
instance ToJSON MyThing where
toJSON = myThingRep
toEncoding = myThingRep
Thoughts? Improvements? (I'd prefer to do this with a TypeFamily for p but not sure how to get the constraints right.)