In this blog I talk about some of the personal programming I do as a hobby. By trade I'm a Java and database developer but I've dabbled in Haskell, front-end development, etc. I'm currently working as an architect but still enjoy getting my fingers dirty in code!

Friday, June 20, 2008

Serializing Haskell objects to JSON

I'm trying to do some simple serialization of Haskell objects to save some state to disk. After tearing some of my hair out debugging parse errors due to silly code I'd written in Read instances declarations, I've decided to use another approach. I'm going to save objects as JSON, since I've already used that JSON library.The first task is to write generic code that can serialize a Data instance to JSON. This has probably been done somewhere else, but I need to learn, right? So I took a deep breath and dived into Data.Generics.I quickly rounded up the issues I would face. Most notably, Strings and lists are accessed without any syntaxic sugar, so to speak: Strings are lists of Char, and lists are made of two fields, the head and the rest. Of course, you say, but from that I need to regenerate String and lists of JSON Value objects.So, to start, how to recognize Strings to treat them differently than other algrebraic types:

isString :: Data a => a -> BoolisString a = (typeOf a) == (typeOf "")

There's probably better ways to do that, just tell me (-:

Lists (that are not strings) can be recognized with abstract representations of constructors, which are equals regardless of the actual type of elements in the list

We first handle Strings, then list, then general objects using constrRep to distinguish between algebraic types that create JSON objects with the proper field names (using constrFields) and other types for JSON primitives.

And that's it for the serialization! The Generics package is not that hard to use but you have to look up examples to figure out how actually use the functions like gmapQ and such...

Now, I have to work on the opposite process: given a type and JSON data, reconstruct the objects... More Haskell fun!

Funny, I mentioned that blog post in the next blog entry about deserializing... Yes, you need to specify that your objects derive from Data. I've realized that some structures like Data.Map or Data.Set error on toConstr and such so they won't work, I'll work on implementing support for those