Serializing a suds object in python Serializing a suds object in python python python

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.