Serializing a suds object in python
I have been using following approach to convert Suds object into JSON:
from suds.sudsobject import asdictdef recursive_asdict(d): """Convert Suds object into serializable format.""" out = {} for k, v in asdict(d).items(): if hasattr(v, '__keylist__'): out[k] = recursive_asdict(v) elif isinstance(v, list): out[k] = [] for item in v: if hasattr(item, '__keylist__'): out[k].append(recursive_asdict(item)) else: out[k].append(item) else: out[k] = v return outdef suds_to_json(data): return json.dumps(recursive_asdict(data))
Yep, I confirm the explanation I gave in the answer you refer to -- dynamically generated classes are not easily picklable (nor otherwise easily serializable), you need to extract all the state information, pickle that state, and reconstruct the tricky sudsobject on retrieval if you really insist on using it;-).
Here is what I came up with before researching and finding this answer. This actually works well for me on complex suds responses and also on other objects such as __builtins__
since the solution is suds agnostic:
import datetimedef object_to_dict(obj): if isinstance(obj, (str, unicode, bool, int, long, float, datetime.datetime, datetime.date, datetime.time)): return obj data_dict = {} try: all_keys = obj.__dict__.keys() # vars(obj).keys() except AttributeError: return obj fields = [k for k in all_keys if not k.startswith('_')] for field in fields: val = getattr(obj, field) if isinstance(val, (list, tuple)): data_dict[field] = [] for item in val: data_dict[field].append(object_to_dict(item)) else: data_dict[field] = object_to_dict(val) return data_dict
This solution works and is actually faster. It also works on objects that don't have the __keylist__
attribute.
I ran a benchmark 100 times on a complex suds output object, this solutions run time was 0.04 to .052 seconds (0.045724287 average). While recursive_asdict
solution above ran in .082 to 0.102 seconds so nearly double (0.0829765582 average).
I then went back to the drawing board and re-did the function to get more performance out of it, and it does not need the datetime
import. I leveraged in using the __keylist__
attribute, so this will not work on other objects such as __builtins__
but works nicely for suds object output:
def fastest_object_to_dict(obj): if not hasattr(obj, '__keylist__'): return obj data = {} fields = obj.__keylist__ for field in fields: val = getattr(obj, field) if isinstance(val, list): # tuple not used data[field] = [] for item in val: data[field].append(fastest_object_to_dict(item)) else: data[field] = fastest_object_to_dict(val) return data
The run time was 0.18 - 0.033 seconds (0.0260889721 average), so nearly 4x as faster than the recursive_asdict
solution.