My goal is to turn MyData (which has a ToJSON instance) into an Aeson.Object (I need it in the form of an Aeson.Object because I merge it with an other Aeson.Object).
I managed to achieve this goal using the following code which compiles:
myDataToAesonObject :: MyData -> Aeson.Object
myDataToAesonObject myData = aesonValueToAesonObject $ toJSON myData
aesonValueToAesonObject :: Aeson.Value -> Aeson.Object
aesonValueToAesonObject (Aeson.Object value) = value
But as a programmer who is still learning Haskell, that neither feels like a best practice to me nor do I have any ideas how to make it cleaner.
It does not feel like a best practice because somebody might misuse the aesonValueToAesonObject function and apply it (for instance) to an Aeson.Value which holds an array. I suspect this would lead to an error. Thus I would like to have something like a toJSON function which returns an Aeson.Object instead of an Aeson.Value in the first place, because it is already a known fact that myData can only be an object.
I hope you understand what I try to say.
Perhaps the best approach - certainly one of the most idiomatic approaches in Haskell - would be to have your
aesonValueToAesonObject(and hence the other function too which uses it) return aMaybe Object:This avoids the most obvious flaw with your version - that if supplied a JSON value of the wrong "type", the program will simply crash with no possibility of recovery. By using
Maybeyou allow code that uses this function to determine whether the JSON representation is an object or not, and if so to extract it, otherwise to do whatever is best in the context of whatever that code is doing: