Wednesday, December 2, 2009

Groovy Serialization - Part 2 - Objects

In my previous post I discussed the serialization of simple Groovy data structures. Arbitrary objects can also be serialized using ConfigObject and ConfigSluper and a little trickery. The fact Groovy config files may also contain code makes this all possible.

In order to instantiate objects inside a Groovy config file, you need import the referenced objects. You also need to override the toString to create the proper instantiation string.


package MyPackage
class MyObject {
def data;
String toString() {
def serializedString = "new MyObject( data : '${data}' )"
return serializedString
}
}

//create the datastructure
def myObject = new MyObject( data: 'wtf')
def configObj = new ConfigObject()
configObj.testing = [1, 2, 3]
configObj.nested = [ objects : myObject ]

//serialize it
new File( 'newout.groovy' ).withWriter{ writer ->
writer.write( "import ${myObject.getClass().getName()}\n" )
configObj.writeTo( writer )
}


Parsing it is simple:

def config = new ConfigSlurper().parse(new File('newout.groovy').toURL())
println config


Finally one could use .metaClass to override the toString of any Java object and make it work with this serialization technique. Be careful not to shoot yourself in the foot by doing this, as other code might expect the regular toString().

Labels: ,

Tuesday, December 1, 2009

Groovy Serialization

Groovy's lists and maps provide the simple building blocks of more complex structures. Occasionally you want to serialize these complex structures to files/streams/whatever. Previously I wrote about using JSON with Groovy. While this is still my weapon of choice for this problem, another alternative would be to use the ConfigObject and the ConfigSlurper classes from the Groovy API.

Here's how you would serialize the data using this method:

//create the datastructure
def configObj = new ConfigObject()
configObj.testing = [1, 2, 3]
configObj.nested = [ objects : 'wtf' ]

//serialize it
new File( 'newout.groovy' ).withWriter{ writer ->
configObj.writeTo( writer )
}


Then when you want to parse it:

def config = new ConfigSlurper().parse(new File('newout.groovy').toURL())
println config


One disadvantage of this method is that the highest level structure must be a map, since that's what ConfigObject inherits from. The data also contains a lot of white-space formatting. Which could be a good or bad depending on the problem you're solving.

Labels: ,