Using JSON in Haskell to serialize a record

I worked on a very small program to get information about Half Life 2 servers (using the protocol-srcds library ). The workflow is pretty simple; it takes a list of servers from a file, requests each of them and writes the output to another file (which is read by a PHP script to display, since I am attached to vBulletin). It would be nice if it were done in SQL or something like that, but seeing that I'm still just learning, this step is too far now!

In any case, my question is about serialization, namely serialization in JSON. At the moment, I wrote a scrappy helper jsonify , such that:

 jsonify (Just (SRCDS.GameServerInfo serverVersion serverName serverMap serverMod serverModDesc serverAppId serverPlayers serverMaxPlayers serverBots serverType serverOS serverPassword serverSecure serverGameVersioning)) = toJSObject [ ("serverName", serverName) , ("serverMap", serverMap) , ("serverPlayers", show serverPlayers) , ("serverMaxPlayers", show serverMaxPlayers) ] 

(I am using the Text.JSON package). This is obviously not perfect. At this point, however, I don’t understand how to use instances to define serializers for records, and my attempts to do this met a wall of frustration with the type system.

Can someone please guide me through the “right” way to do this? How can I define an instance that serializes a record? What functions should be used in instance (showJSON?).

Thanks in advance for your help.

+4
source share
2 answers

You might want to use Data.Aeson , which could be considered the successor to Text.JSON .

With aeson you define individual instances for serialization / deserialization (using Text.JSON you need to determine both directions, even if you need only one, otherwise compilation will annoy you if you do not freeze the warning in this way) and it provides several statements that make the defining instances are a little more compact, for example the example from @hammar's answer might be written a little less noisy, as shown below with the aeson API:

 instance ToJSON SRCDS.GameServerInfo where toJSON (SRCDS.GameServerInfo {..}) = object [ "serverName" .= serverName , "serverMap" .= serverMap , "serverPlayers" .= serverPlayers , "serverMaxPlayers" .= serverMaxPlayers ] 
+6
source

One simple thing you can do is save the wildcards to shorten the template code.

Regarding system problems of your type, it’s hard to give help without seeing the error messages and what you have tried so far, however I suspect that one thing that can be confusing is that the result toJSObject should be wrapped in the JSObject data JSObject , since the showJSON return showJSON must be JSValue . Similarly, the values ​​of your object must also be of type JSValue . The easiest way to do this is to use a JSON instance and call showJSON to convert the values.

 instance JSON SRCDS.GameServerInfo where showJSON (SRCDS.GameServerInfo {..}) = JSObject $ toJSObject [ ("serverName", showJSON serverName) , ("serverMap", showJSON serverMap) , ("serverPlayers", showJSON serverPlayers) , ("serverMaxPlayers", showJSON serverMaxPlayers) ] 
+1
source

All Articles