snippetpythonMinor
A better way to convert an SQLObject instance into a dict
Viewed 0 times
dictsqlobjectconvertintowaybetterinstance
Problem
I've got this function which returns an SQLObject instance as a dict (taking into account inherited classes, properties, etc). It doesn't work right now on SQLObject classes which inherit from another class but add new attributes, so that's a work in progress, but I feel like this could be done smarter/better in Python.
What do you think?
PS the purpose of this is to allow a generic presentation of an object as a JSON document. It returns a dict which can be then given to json.dumps. If you've got a different way to convert an SQLObject to a JSON doc, that would be cool as well
What do you think?
PS the purpose of this is to allow a generic presentation of an object as a JSON document. It returns a dict which can be then given to json.dumps. If you've got a different way to convert an SQLObject to a JSON doc, that would be cool as well
def sqlobject_to_dict(obj):
obj_dict = {}
cls_name = type(obj)
has_props = False
for attr in vars(cls_name):
attr_parent = type(getattr(obj, attr)).__bases__[0]
if isinstance(getattr(cls_name, attr), property):
has_props = True
if isinstance(getattr(obj, attr), Decimal):
obj_dict[attr] = float(getattr(obj, attr))
elif isinstance(getattr(obj, attr), list):
dict_list = []
for list_item in getattr(obj, attr):
dict_list.append(sqlobject_to_dict(list_item))
obj_dict[attr] = dict_list
elif isinstance(getattr(obj, attr), dict):
dict_dict = {}
for key, val in getattr(obj, attr):
dict_dict[key] = sqlobject_to_dict(val)
obj_dict[attr] = dict_dict
elif attr_parent == SQLObject:
obj_dict[attr] = sqlobject_to_dict(getattr(obj, attr))
else:
obj_dict[attr] = getattr(obj, attr)
elif not has_props and attr_parent != SQLObject:
if "_get_" in attr:
attr_name = '_'.join(attr.split('_', 3)[3:])
if hasattr(obj, attr_name):
obj_dict[attr_name] = getattr(obj, attr_name)
return obj_dictSolution
def sqlobject_to_dict(obj):
obj_dict = {}
cls_name = type(obj)That's not a name, its a class object
has_props = False
for attr in vars(cls_name):
attr_parent = type(getattr(obj, attr)).__bases__[0]You have
getattr(obj, attr) over and over and over. Do it once, and store it in a local variableif isinstance(getattr(cls_name, attr), property):
has_props = True
if isinstance(getattr(obj, attr), Decimal):
obj_dict[attr] = float(getattr(obj, attr))
elif isinstance(getattr(obj, attr), list):
dict_list = []
for list_item in getattr(obj, attr):
dict_list.append(sqlobject_to_dict(list_item))
obj_dict[attr] = dict_listI recommend doing
obj_dict[attr] = map(sql_object_dict, getattr(obj, attr))elif isinstance(getattr(obj, attr), dict):
dict_dict = {}
for key, val in getattr(obj, attr):Don't you need
.items()?dict_dict[key] = sqlobject_to_dict(val)
obj_dict[attr] = dict_dict
I'd do
obj_dict[attr] = dict( (key, sql_object_to_dict(value)) for key, value in getattr(obj, attr) )elif attr_parent == SQLObject:
Why did you fetch
attr_parent instead of using isinstance?obj_dict[attr] = sqlobject_to_dict(getattr(obj, attr))
else:
obj_dict[attr] = getattr(obj, attr)Is a default really a good idea? There may some sort of attribute with isn't valid JSON that makes it through.
elif not has_props and attr_parent != SQLObject:
if "_get_" in attr:
attr_name = '_'.join(attr.split('_', 3)[3:])Thats a confusing way to do that. I'm sure what exactly the form you are trying to match here is, but I think this is a use case for regular expressions.
if hasattr(obj, attr_name):
obj_dict[attr_name] = getattr(obj, attr_name)So I'm guessing you've got various
_get_foo() functions which are invoked by some sort of __getattr__ magic. You stop checking for this once you find a property. (Probably newer objects use properties instead.) I would consider not doing the has_props thing. It makes your code less clear, and probably doesn't make much difference performance wise.return obj_dictCode Snippets
def sqlobject_to_dict(obj):
obj_dict = {}
cls_name = type(obj)has_props = False
for attr in vars(cls_name):
attr_parent = type(getattr(obj, attr)).__bases__[0]if isinstance(getattr(cls_name, attr), property):
has_props = True
if isinstance(getattr(obj, attr), Decimal):
obj_dict[attr] = float(getattr(obj, attr))
elif isinstance(getattr(obj, attr), list):
dict_list = []
for list_item in getattr(obj, attr):
dict_list.append(sqlobject_to_dict(list_item))
obj_dict[attr] = dict_listelif isinstance(getattr(obj, attr), dict):
dict_dict = {}
for key, val in getattr(obj, attr):obj_dict[attr] = sqlobject_to_dict(getattr(obj, attr))
else:
obj_dict[attr] = getattr(obj, attr)Context
StackExchange Code Review Q#7420, answer score: 4
Revisions (0)
No revisions yet.