The purpose of writing separate Reader/Writer classes is to support different output processing - write to console, write to bytes, write to a JSON string, whatever. The important thing is that each of the classes Struct1, Struct2, etc. knows what attributes are significant for saving their state. This is the philosophy used by the pickle module.
class Struct1(object):
fields = ('a','b','c')
...
class Struct2(object):
fields = ('foo', 'bar', 'baz')
...
Now various writer classes can be written using this metadata, without having to write class-specific code:
class StructWriter(object):
packTypeMap = {int:'i', float:'f', str:'s'}
def write(self, obj):
fields = obj.fields
packstring = ''.join(packTypeMap[type(f)] for f in fields)
packargs = (getattr(obj,f) for f in fields)
return struct.pack(packstring, *packargs)
class DictWriter(object):
def write(self, obj):
return dict((f, getattr(obj,f)) for f in obj.fields)
class JSONWriter(object):
jsonTypeMap = {str:lambda s:"'"+s+"'"}
defaultJsonFunc = lambda x:str(x)
def write(self, obj):
# not really recommended to roll your own strings, but for illustration...
fields = obj.fields
outargs = (getattr(obj,f) for f in fields)
outvals = (jsonTypeMap.get(type(arg),defaultJsonFunc)(arg)
for arg in outargs)
return ('{' +
','.join("'%s':%s" % field_val for field_val in zip(fields, outvals))
'}')
class ZipJSONWriter(JSONWriter):
def write(self, obj):
import zlib
return zlib.compress(super(ZipJSONWriter,self).write(obj))
class HTMLTableWriter(object):
def write(self, obj):
out = "<table>"
for field in obj.fields:
out += "<tr><td>%s</td><td>%s</td></tr>" % (field, getattr(obj,field))
out += "</table>"
return out