'''
Created on 2011-10-11
@author: jacekf
Responsible for converting return values into cleanly serializable dict/tuples/lists
for JSON/XML/YAML output
'''
import collections
import logging
import json
from twisted.python import log
primitives = (int, float, bool, str,str)
def convertForSerialization(obj):
"""Converts anything (clas,tuples,list) to the safe serializable equivalent"""
try:
if type(obj) in primitives:
# no conversion
return obj
elif isinstance(obj, dict):
return traverseDict(obj)
elif isClassInstance(obj):
return convertClassToDict(obj)
elif isinstance(obj,collections.Iterable) and not isinstance(obj,str):
# iterable
values = []
for val in obj:
values.append(convertForSerialization(val))
return values
else:
# return as-is
return obj
except AttributeError as ex:
log.msg(ex,logLevel=logging.WARN)
return obj
def convertClassToDict(clazz):
"""Converts a class to a dictionary"""
properties = {}
for prop,val in clazz.__dict__.items():
#omit private fields
if not prop.startswith("_"):
properties[prop] = val
return traverseDict(properties)
def traverseDict(dictObject):
"""Traverses a dict recursively to convertForSerialization any nested classes"""
newDict = {}
for prop,val in dictObject.items():
newDict[prop] = convertForSerialization(val)
return newDict
def convertToJson(obj):
"""Converts to JSON, including Python classes that are not JSON serializable by default"""
try:
return json.dumps(obj)
except Exception as ex:
raise RuntimeError(str(ex))
def generateXml(obj):
"""Generates basic XML from an object that has already been converted for serialization"""
if isinstance(obj, dict):
return getXML_dict(obj, "item")
elif isinstance(obj,collections.Iterable):
return "%s
" % getXML(obj, "item")
else:
raise RuntimeError("Unable to convert to XML: %s" % obj)
def isClassInstance(obj):
"""Checks if a given obj is a class instance"""
return getattr(obj, "__class__",None) != None and not isinstance(obj,dict) and not isinstance(obj,tuple) and not isinstance(obj,list) and not isinstance(obj,str)
## {{{ http://code.activestate.com/recipes/440595/ (r2)
def getXML(obj, objname=None):
"""getXML(obj, objname=None)
returns an object as XML where Python object names are the tags.
>>> u={'UserID':10,'Name':'Mark','Group':['Admin','Webmaster']}
>>> getXML(u,'User')
'10MarkAdminWebmaster'
"""
if obj == None:
return ""
if not objname:
objname = "item"
adapt={
dict: getXML_dict,
list: getXML_list,
tuple: getXML_list,
}
if obj.__class__ in adapt:
return adapt[obj.__class__](obj, objname)
else:
return "<%(n)s>%(o)s%(n)s>"%{'n':objname,'o':str(obj)}
def getXML_dict(indict, objname=None):
h = "<%s>"%objname
for k, v in list(indict.items()):
h += getXML(v, k)
h += "%s>"%objname
return h
def getXML_list(inlist, objname=None):
h = ""
for i in inlist:
h += getXML(i, objname)
return h
## end of http://code.activestate.com/recipes/440595/ }}}